home *** CD-ROM | disk | FTP | other *** search
/ MacWorld 1999 May / Macworld (1999-05).dmg / Updaters / SpriteWorld 2.2.1 Update / Source Updates / SpriteWorld.c < prev    next >
Text File  |  1999-03-02  |  68KB  |  2,307 lines

  1. ///--------------------------------------------------------------------------------------
  2. //    SpriteWorld.c
  3. //
  4. //    Portions are copyright: © 1991-94 Tony Myles, All rights reserved worldwide.
  5. //
  6. //    Description:    implementation of the sprite world architecture
  7. ///--------------------------------------------------------------------------------------
  8.  
  9.  
  10. #ifndef __SWCOMMON__
  11. #include "SWCommonHeaders.h"
  12. #endif
  13.  
  14. #ifndef __QUICKDRAW__
  15. #include <QuickDraw.h>
  16. #endif
  17.  
  18. #ifndef __MEMORY__
  19. #include <Memory.h>
  20. #endif
  21.  
  22. #ifndef __GESTALT__
  23. #include <Gestalt.h>
  24. #endif
  25.  
  26. #ifndef __TIMER__
  27. #include <Timer.h>
  28. #endif
  29.  
  30. #ifndef __SPRITEWORLDUTILS__
  31. #include "SpriteWorldUtils.h"
  32. #endif
  33.  
  34. #ifndef __SPRITEWORLD__
  35. #include "SpriteWorld.h"
  36. #endif
  37.  
  38. #ifndef __SPRITELAYER__
  39. #include "SpriteLayer.h"
  40. #endif
  41.  
  42. #ifndef __SPRITE__
  43. #include "Sprite.h"
  44. #endif
  45.  
  46. #ifndef __SPRITEFRAME__
  47. #include "SpriteFrame.h"
  48. #endif
  49.  
  50. #ifndef __BLITPIXIE__
  51. #include "BlitPixie.h"
  52. #endif
  53.  
  54. #ifndef __RETRACE__
  55. #include <Retrace.h>
  56. #endif
  57.  
  58. #ifndef __SCROLLING__
  59. #include "Scrolling.h"
  60. #endif
  61.  
  62. #ifndef __TILING__
  63. #include "Tiling.h"
  64. #endif
  65.  
  66.  
  67. SInt8             gSWmmuMode;
  68. short            gProcessorType;                // 
  69. RgnHandle         gCollisionSectRgn = NULL;    ///  Initialized by SWEnterSpriteWorld
  70. RgnHandle         gCollisionSpareRgn = NULL;    // 
  71. SpritePtr        gCurrentSpriteBeingDrawn = NULL;
  72. SpriteWorldPtr    gCleanUpSpriteWorldP = NULL;
  73.  
  74.  
  75. ///--------------------------------------------------------------------------------------
  76. //    SWEnterSpriteWorld
  77. ///--------------------------------------------------------------------------------------
  78.  
  79. SW_FUNC OSErr SWEnterSpriteWorld(void)
  80. {
  81.     OSErr    err = noErr;
  82.  
  83.     gSWmmuMode = GetMMUMode();
  84.     
  85.     if ( !SWHasSystem7() )
  86.     {
  87.         err = kSystemTooOldErr;
  88.     }
  89.     
  90.     SWGetProcessorType(&gProcessorType);
  91.     
  92.     if (gCollisionSectRgn == NULL && gCollisionSpareRgn == NULL)
  93.     {
  94.         gCollisionSectRgn = NewRgn();
  95.         gCollisionSpareRgn = NewRgn();
  96.     }
  97.     else
  98.     {
  99.         err = kAlreadyCalledErr;
  100.     }
  101.     
  102.     SWSetStickyIfError( err );
  103.     return err;
  104. }
  105.  
  106.  
  107. ///--------------------------------------------------------------------------------------
  108. //    SWCreateSpriteWorld
  109. ///--------------------------------------------------------------------------------------
  110.  
  111. SW_FUNC OSErr SWCreateSpriteWorld(
  112.     GDHandle            mainGDH,
  113.     SpriteWorldPtr        *spriteWorldP,
  114.     FramePtr            windowFrameP,
  115.     FramePtr            backFrameP,
  116.     FramePtr            workFrameP,
  117.     short                maxDepth)
  118. {
  119.     OSErr            err;
  120.     SpriteWorldPtr    tempSpriteWorldP;
  121.     PixMapHandle    basePixMap;
  122.     
  123.  
  124.     err = noErr;
  125.     *spriteWorldP = NULL;
  126.  
  127.     tempSpriteWorldP = (SpriteWorldPtr)NewPtrClear((Size)sizeof(SpriteWorldRec));
  128.     if (tempSpriteWorldP == NULL)
  129.         err = MemError();
  130.     
  131.     if (err == noErr)
  132.     {
  133.             // Create the deadSpriteLayerP, but don't add it to the linked layer list
  134.         err = SWCreateSpriteLayer(&tempSpriteWorldP->deadSpriteLayerP);
  135.         if (err != noErr)
  136.             DisposePtr((Ptr)tempSpriteWorldP);
  137.     }
  138.  
  139.     if (err == noErr)
  140.     {
  141.         basePixMap = (**mainGDH).gdPMap;
  142.         if ( maxDepth == 0 || (**basePixMap).pixelSize <= maxDepth )
  143.         {
  144.             tempSpriteWorldP->pixelDepth = (**basePixMap).pixelSize;
  145.         }
  146.         else
  147.         {
  148.             tempSpriteWorldP->pixelDepth = maxDepth;
  149.         }
  150.         
  151.         tempSpriteWorldP->headSpriteLayerP = NULL;
  152.         tempSpriteWorldP->tailSpriteLayerP = NULL;
  153.         
  154.         tempSpriteWorldP->mainSWGDH = mainGDH;
  155.         tempSpriteWorldP->windowFrameP = windowFrameP;
  156.         tempSpriteWorldP->extraBackFrameP = NULL;
  157.         tempSpriteWorldP->backFrameP = backFrameP;
  158.         tempSpriteWorldP->workFrameP = workFrameP;
  159.         tempSpriteWorldP->offscreenDrawProc = SWStdWorldDrawProc;
  160.         tempSpriteWorldP->screenDrawProc = SWStdWorldDrawProc;
  161.         tempSpriteWorldP->doubleRectDrawProc = NULL;
  162.         tempSpriteWorldP->postEraseCallBack = NULL;
  163.         tempSpriteWorldP->postDrawCallBack = NULL;
  164.         tempSpriteWorldP->windRect = windowFrameP->frameRect;
  165.         tempSpriteWorldP->backRect = backFrameP->frameRect;
  166.         tempSpriteWorldP->originalWindRect = windowFrameP->frameRect;
  167.         tempSpriteWorldP->originalBackRect = backFrameP->frameRect;
  168.         
  169.         tempSpriteWorldP->headUpdateRectP = NULL;
  170.         
  171.         tempSpriteWorldP->scrollRectMoveBounds.left = 0;
  172.         tempSpriteWorldP->scrollRectMoveBounds.top = 0;
  173.         tempSpriteWorldP->scrollRectMoveBounds.right = 32767;
  174.         tempSpriteWorldP->scrollRectMoveBounds.bottom = 32767;
  175.         tempSpriteWorldP->horizScrollRectOffset = 0;
  176.         tempSpriteWorldP->vertScrollRectOffset = 0;
  177.         tempSpriteWorldP->horizScrollDelta = 0;
  178.         tempSpriteWorldP->vertScrollDelta = 0;
  179.         tempSpriteWorldP->worldMoveProc = NULL;
  180.         
  181.             // Make sure visScrollRect is at 0,0 top-left corner
  182.         tempSpriteWorldP->visScrollRect = windowFrameP->frameRect;
  183.         OffsetRect(&tempSpriteWorldP->visScrollRect,
  184.             -tempSpriteWorldP->visScrollRect.left, 
  185.             -tempSpriteWorldP->visScrollRect.top);
  186.         tempSpriteWorldP->offscreenScrollRect = tempSpriteWorldP->visScrollRect;
  187.         tempSpriteWorldP->oldVisScrollRect = tempSpriteWorldP->visScrollRect;
  188.         
  189.         tempSpriteWorldP->tileLayerArray = NULL;
  190.         tempSpriteWorldP->tilingCache = NULL;
  191.         tempSpriteWorldP->changedTiles = NULL;
  192.         tempSpriteWorldP->tilingIsInitialized = false;
  193.         tempSpriteWorldP->tilingIsOn = false;
  194.         tempSpriteWorldP->numTilesChanged = 0;
  195.         tempSpriteWorldP->tileChangeProc = NULL;
  196.         tempSpriteWorldP->tileRectDrawProc = SWDrawTilesInRect;
  197.         tempSpriteWorldP->tileMaskDrawProc = SWStdSpriteDrawProc;
  198.         tempSpriteWorldP->partialMaskDrawProc = SWStdSpriteDrawProc;
  199.         
  200.         tempSpriteWorldP->frameHasOccurred = false;
  201.         tempSpriteWorldP->fpsTimeInterval = 0L;
  202.         
  203.         tempSpriteWorldP->lastMicroseconds.hi = 0L;
  204.         tempSpriteWorldP->lastMicroseconds.lo = 0L;
  205.         tempSpriteWorldP->runningTimeCount = 0L;
  206.         
  207.         tempSpriteWorldP->vblTaskRec.hasVBLFired = true;
  208.         tempSpriteWorldP->usingVBL = false;
  209.         
  210.         SWClearStickyError();
  211.  
  212.         *spriteWorldP = tempSpriteWorldP;
  213.     }
  214.  
  215.     return err;
  216. }
  217.  
  218.  
  219. ///--------------------------------------------------------------------------------------
  220. //    SWCreateSpriteWorldFromWindow
  221. ///--------------------------------------------------------------------------------------
  222.  
  223. SW_FUNC OSErr SWCreateSpriteWorldFromWindow(
  224.     SpriteWorldPtr*    spriteWorldP,
  225.     CWindowPtr        srcWindowP,
  226.     Rect*            worldRectP,
  227.     Rect*            offscreenRectP,
  228.     short            maxDepth)
  229. {
  230.     OSErr             err = noErr;
  231.     FramePtr         windowFrameP, backFrameP, workFrameP;
  232.     Rect             tempRect, globalRect, windRect;
  233.     GDHandle        mainGDH;
  234.     PixMapHandle    basePixMap;
  235.     short            depth;
  236.     
  237.     
  238.     *spriteWorldP = NULL;
  239.     windowFrameP = backFrameP = workFrameP = NULL;
  240.     
  241.     SetPort( (WindowPtr)srcWindowP );
  242.     
  243.     windRect = (worldRectP == NULL) ? srcWindowP->portRect : *worldRectP;
  244.     
  245.     globalRect = windRect;
  246.     LocalToGlobal((Point *)&globalRect.top);
  247.     LocalToGlobal((Point *)&globalRect.bottom);
  248.     
  249.     
  250.     mainGDH = GetMaxDevice( &globalRect );
  251.     SetGDevice( mainGDH );
  252.     basePixMap = (**mainGDH).gdPMap;
  253.     if ( maxDepth == 0 || (**basePixMap).pixelSize <= maxDepth )
  254.     {
  255.         depth = (**basePixMap).pixelSize;
  256.     }
  257.     else
  258.     {
  259.         depth = maxDepth;
  260.     }
  261.     
  262.     if ( srcWindowP->portVersion < (short)0xC000 )
  263.     {
  264.         err = kNotCWindowErr;
  265.     }
  266.     
  267.         // If a custom offscreenRect has been requested, use it instead.
  268.     if (offscreenRectP == NULL)
  269.         tempRect = windRect;
  270.     else
  271.         tempRect = *offscreenRectP;
  272.     
  273.         // offset Rect to (0,0) for back and work frames
  274.     OffsetRect(&tempRect, -tempRect.left, -tempRect.top);
  275.     
  276.     if (err == noErr)
  277.     {
  278.             // create window frame
  279.         err = SWCreateWindowFrame(&windowFrameP, &windRect, tempRect.bottom);
  280.     }
  281.     
  282.     if (err == noErr)
  283.     {
  284.             // create back drop frame
  285.         err = SWCreateFrame(mainGDH, &backFrameP, &tempRect, depth);
  286.     }
  287.  
  288.     if (err == noErr)
  289.     {
  290.             // create work frame
  291.         err = SWCreateFrame(mainGDH, &workFrameP, &tempRect, depth);
  292.     }
  293.  
  294.  
  295.     if (err == noErr)
  296.     {
  297.             // create sprite world
  298.         err = SWCreateSpriteWorld(mainGDH, spriteWorldP, windowFrameP, 
  299.                 backFrameP, workFrameP, maxDepth);
  300.     }
  301.  
  302.     if (err != noErr)
  303.     {
  304.             // an error occurred so dispose of anything we managed to create
  305.  
  306.         if (windowFrameP != NULL)
  307.         {
  308.             SWDisposeWindowFrame(&windowFrameP);
  309.         }
  310.  
  311.         if (backFrameP != NULL)
  312.         {
  313.             SWDisposeFrame(&backFrameP);
  314.         }
  315.  
  316.         if (workFrameP != NULL)
  317.         {
  318.             SWDisposeFrame(&workFrameP);
  319.         }
  320.     }
  321.     
  322.     SWSetStickyIfError( err );
  323.     return err;
  324. }
  325.  
  326.  
  327. ///--------------------------------------------------------------------------------------
  328. //    SWDisposeSpriteWorld
  329. ///--------------------------------------------------------------------------------------
  330.  
  331. SW_FUNC void SWDisposeSpriteWorld(
  332.     SpriteWorldPtr    *spriteWorldPP)
  333. {
  334.     SpriteWorldPtr    spriteWorldP = *spriteWorldPP;
  335.     SpriteLayerPtr     curLayerP;
  336.     SpritePtr         curSpriteP;
  337.     
  338.     
  339.     if (spriteWorldP != NULL)
  340.     {
  341.         SWUnlockSpriteWorld(spriteWorldP);
  342.             
  343.         while ((curLayerP = SWGetNextSpriteLayer(spriteWorldP, NULL)) != NULL)
  344.         {        
  345.                 // dispose of each sprite in the layer
  346.             while ((curSpriteP = SWGetNextSprite(curLayerP, NULL)) != NULL)
  347.             {
  348.                 SWRemoveSprite(curSpriteP);
  349.                 SWDisposeSprite(&curSpriteP);
  350.             }
  351.             
  352.                 // dispose of each layer in the spriteWorld
  353.             SWRemoveSpriteLayer(spriteWorldP, curLayerP);
  354.             SWDisposeSpriteLayer(&curLayerP);
  355.         }
  356.         
  357.         SWDisposeAllSpritesInLayer(spriteWorldP->deadSpriteLayerP);
  358.         SWDisposeSpriteLayer(&spriteWorldP->deadSpriteLayerP);
  359.         
  360.         SWDisposeFrame(&spriteWorldP->backFrameP);
  361.         SWDisposeFrame(&spriteWorldP->workFrameP);
  362.         SWDisposeFrame(&spriteWorldP->extraBackFrameP);
  363.  
  364.         SWDisposeWindowFrame(&spriteWorldP->windowFrameP);
  365.         
  366.         SWExitTiling(spriteWorldP);
  367.         SWSyncSpriteWorldToVBL(spriteWorldP, false);
  368.         
  369.         DisposePtr((Ptr)spriteWorldP);
  370.         *spriteWorldPP = NULL;    // Set original pointer to NULL
  371.     }
  372. }
  373.  
  374.  
  375. ///--------------------------------------------------------------------------------------
  376. //    SWExitSpriteWorld
  377. ///--------------------------------------------------------------------------------------
  378.  
  379. SW_FUNC void SWExitSpriteWorld(void)
  380. {
  381.     if (gCollisionSectRgn != NULL)
  382.         DisposeRgn(gCollisionSectRgn);
  383.     if (gCollisionSpareRgn != NULL)
  384.         DisposeRgn(gCollisionSpareRgn);
  385.     
  386.     gCollisionSectRgn = NULL;
  387.     gCollisionSpareRgn = NULL;
  388. }
  389.  
  390.  
  391. ///--------------------------------------------------------------------------------------
  392. //    SWAddSpriteLayer
  393. ///--------------------------------------------------------------------------------------
  394.  
  395. SW_FUNC void SWAddSpriteLayer(
  396.     SpriteWorldPtr        spriteWorldP,
  397.     SpriteLayerPtr        newSpriteLayerP)
  398. {
  399.     SpriteLayerPtr     tailSpriteLayerP = spriteWorldP->tailSpriteLayerP;
  400.     
  401.     SW_ASSERT(spriteWorldP != NULL);
  402.  
  403.     if (tailSpriteLayerP != NULL)
  404.         tailSpriteLayerP->nextSpriteLayerP = newSpriteLayerP;
  405.     else
  406.         spriteWorldP->headSpriteLayerP = newSpriteLayerP;
  407.     
  408.     newSpriteLayerP->prevSpriteLayerP = tailSpriteLayerP;
  409.     newSpriteLayerP->nextSpriteLayerP = NULL;
  410.  
  411.         // make the new layer the tail
  412.     spriteWorldP->tailSpriteLayerP = newSpriteLayerP;
  413. }
  414.  
  415.  
  416. ///--------------------------------------------------------------------------------------
  417. //    SWRemoveSpriteLayer
  418. ///--------------------------------------------------------------------------------------
  419.  
  420. SW_FUNC void SWRemoveSpriteLayer(
  421.     SpriteWorldPtr    spriteWorldP,
  422.     SpriteLayerPtr    oldSpriteLayerP)
  423. {    
  424.     SW_ASSERT(spriteWorldP != NULL);
  425.     
  426.         // is there a next layer?
  427.     if (oldSpriteLayerP->nextSpriteLayerP != NULL)
  428.     {
  429.             // link the next layer to the prev layer
  430.         oldSpriteLayerP->nextSpriteLayerP->prevSpriteLayerP = oldSpriteLayerP->prevSpriteLayerP;
  431.     }
  432.     else
  433.     {
  434.             // make the prev layer the tail
  435.         spriteWorldP->tailSpriteLayerP = oldSpriteLayerP->prevSpriteLayerP;
  436.     }
  437.  
  438.         // is there a prev layer?
  439.     if (oldSpriteLayerP->prevSpriteLayerP != NULL)
  440.     {
  441.             // link the prev layer to the next layer
  442.         oldSpriteLayerP->prevSpriteLayerP->nextSpriteLayerP = oldSpriteLayerP->nextSpriteLayerP;
  443.     }
  444.     else
  445.     {
  446.             // make the next layer the head
  447.         spriteWorldP->headSpriteLayerP = oldSpriteLayerP->nextSpriteLayerP;
  448.     }
  449. }
  450.  
  451.  
  452. ///--------------------------------------------------------------------------------------
  453. //    SWSwapSpriteLayer
  454. ///--------------------------------------------------------------------------------------
  455.  
  456. SW_FUNC void SWSwapSpriteLayer(
  457.     SpriteWorldPtr    spriteWorldP,
  458.     SpriteLayerPtr    srcSpriteLayerP,
  459.     SpriteLayerPtr    dstSpriteLayerP)
  460. {
  461.     register SpriteLayerPtr        swapSpriteLayerP;
  462.     
  463.     SW_ASSERT(spriteWorldP != NULL);
  464.     
  465.         // adjacent Layers are a special case
  466.         
  467.     if ( srcSpriteLayerP->nextSpriteLayerP == dstSpriteLayerP ||
  468.         dstSpriteLayerP->nextSpriteLayerP == srcSpriteLayerP )
  469.     {
  470.         if ( srcSpriteLayerP->nextSpriteLayerP == dstSpriteLayerP )
  471.         {
  472.             if ( srcSpriteLayerP->prevSpriteLayerP != NULL )
  473.                 (srcSpriteLayerP->prevSpriteLayerP)->nextSpriteLayerP = dstSpriteLayerP;
  474.             if ( dstSpriteLayerP->nextSpriteLayerP != NULL )
  475.                 (dstSpriteLayerP->nextSpriteLayerP)->prevSpriteLayerP = srcSpriteLayerP;
  476.             
  477.             dstSpriteLayerP->prevSpriteLayerP = srcSpriteLayerP->prevSpriteLayerP;
  478.             srcSpriteLayerP->nextSpriteLayerP = dstSpriteLayerP->nextSpriteLayerP;
  479.             
  480.             dstSpriteLayerP->nextSpriteLayerP = srcSpriteLayerP;
  481.             srcSpriteLayerP->prevSpriteLayerP = dstSpriteLayerP;
  482.         }
  483.         else
  484.         {
  485.             if ( dstSpriteLayerP->prevSpriteLayerP != NULL )
  486.                 (dstSpriteLayerP->prevSpriteLayerP)->nextSpriteLayerP = srcSpriteLayerP;
  487.             if ( srcSpriteLayerP->nextSpriteLayerP != NULL )
  488.                 (srcSpriteLayerP->nextSpriteLayerP)->prevSpriteLayerP = dstSpriteLayerP;
  489.             
  490.             srcSpriteLayerP->prevSpriteLayerP = dstSpriteLayerP->prevSpriteLayerP;
  491.             dstSpriteLayerP->nextSpriteLayerP = srcSpriteLayerP->nextSpriteLayerP;
  492.             
  493.             srcSpriteLayerP->nextSpriteLayerP = dstSpriteLayerP;
  494.             dstSpriteLayerP->prevSpriteLayerP = srcSpriteLayerP;
  495.         }
  496.     }
  497.     else
  498.     {
  499.         if ( srcSpriteLayerP->prevSpriteLayerP != NULL && 
  500.                 dstSpriteLayerP->prevSpriteLayerP != NULL )
  501.         {
  502.             swapSpriteLayerP = (srcSpriteLayerP->prevSpriteLayerP)->nextSpriteLayerP;
  503.             (srcSpriteLayerP->prevSpriteLayerP)->nextSpriteLayerP = 
  504.                     (dstSpriteLayerP->prevSpriteLayerP)->nextSpriteLayerP;
  505.             (dstSpriteLayerP->prevSpriteLayerP)->nextSpriteLayerP = swapSpriteLayerP;
  506.         }
  507.         
  508.         if ( srcSpriteLayerP->nextSpriteLayerP != NULL && 
  509.                 dstSpriteLayerP->nextSpriteLayerP != NULL )
  510.         {
  511.             swapSpriteLayerP = (srcSpriteLayerP->nextSpriteLayerP)->prevSpriteLayerP;
  512.             (srcSpriteLayerP->nextSpriteLayerP)->prevSpriteLayerP = 
  513.                     (dstSpriteLayerP->nextSpriteLayerP)->prevSpriteLayerP;
  514.             (dstSpriteLayerP->nextSpriteLayerP)->prevSpriteLayerP = swapSpriteLayerP;
  515.         }
  516.         swapSpriteLayerP = srcSpriteLayerP->nextSpriteLayerP;
  517.         srcSpriteLayerP->nextSpriteLayerP = dstSpriteLayerP->nextSpriteLayerP;
  518.         dstSpriteLayerP->nextSpriteLayerP = swapSpriteLayerP;
  519.  
  520.         swapSpriteLayerP = srcSpriteLayerP->prevSpriteLayerP;
  521.         srcSpriteLayerP->prevSpriteLayerP = dstSpriteLayerP->prevSpriteLayerP;
  522.         dstSpriteLayerP->prevSpriteLayerP = swapSpriteLayerP;
  523.     }
  524.  
  525.     if (srcSpriteLayerP->nextSpriteLayerP == NULL)
  526.     {
  527.         spriteWorldP->tailSpriteLayerP = srcSpriteLayerP;
  528.     }
  529.     else if (srcSpriteLayerP->prevSpriteLayerP == NULL)
  530.     {
  531.         spriteWorldP->headSpriteLayerP = srcSpriteLayerP;
  532.     }
  533.  
  534.     if (dstSpriteLayerP->nextSpriteLayerP == NULL)
  535.     {
  536.         spriteWorldP->tailSpriteLayerP = dstSpriteLayerP;
  537.     }
  538.     else if (dstSpriteLayerP->prevSpriteLayerP == NULL)
  539.     {
  540.         spriteWorldP->headSpriteLayerP = dstSpriteLayerP;
  541.     }
  542. }
  543.  
  544.  
  545. ///--------------------------------------------------------------------------------------
  546. //    SWGetNextSpriteLayer
  547. ///--------------------------------------------------------------------------------------
  548.  
  549. SW_FUNC SpriteLayerPtr SWGetNextSpriteLayer(
  550.     SpriteWorldPtr    spriteWorldP,
  551.     SpriteLayerPtr    curSpriteLayerP)
  552. {
  553.     SW_ASSERT(spriteWorldP != NULL);
  554.     
  555.     return (curSpriteLayerP == NULL) ?
  556.             spriteWorldP->headSpriteLayerP :
  557.             curSpriteLayerP->nextSpriteLayerP;
  558. }
  559.  
  560.  
  561. ///--------------------------------------------------------------------------------------
  562. //    SWLockSpriteWorld
  563. ///--------------------------------------------------------------------------------------
  564.  
  565. SW_FUNC void SWLockSpriteWorld(
  566.     SpriteWorldPtr    spriteWorldP)
  567. {
  568.     SpriteLayerPtr curSpriteLayerP;
  569.  
  570.     SW_ASSERT(spriteWorldP != NULL);
  571.     
  572.     SWLockWindowFrame(spriteWorldP->windowFrameP);
  573.     SWLockFrame(spriteWorldP->workFrameP);
  574.     SWLockFrame(spriteWorldP->backFrameP);
  575.     if (spriteWorldP->extraBackFrameP != NULL)
  576.         SWLockFrame(spriteWorldP->extraBackFrameP);
  577.     
  578.     SWLockTiles(spriteWorldP);
  579.  
  580.     curSpriteLayerP = spriteWorldP->headSpriteLayerP;
  581.  
  582.     while (curSpriteLayerP != NULL)
  583.     {
  584.         SWLockSpriteLayer(curSpriteLayerP);
  585.  
  586.         curSpriteLayerP = curSpriteLayerP->nextSpriteLayerP;
  587.     }
  588. }
  589.  
  590.  
  591. ///--------------------------------------------------------------------------------------
  592. //    SWUnlockSpriteWorld
  593. ///--------------------------------------------------------------------------------------
  594.  
  595. SW_FUNC void SWUnlockSpriteWorld(
  596.     SpriteWorldPtr    spriteWorldP)
  597. {
  598.     SpriteLayerPtr curSpriteLayerP;
  599.     
  600.     SW_ASSERT(spriteWorldP != NULL);
  601.  
  602.     SWUnlockWindowFrame(spriteWorldP->windowFrameP);
  603.     SWUnlockFrame(spriteWorldP->backFrameP);
  604.     SWUnlockFrame(spriteWorldP->workFrameP);    
  605.     if (spriteWorldP->extraBackFrameP != NULL)
  606.         SWUnlockFrame(spriteWorldP->extraBackFrameP);
  607.     
  608.     SWUnlockTiles(spriteWorldP);
  609.  
  610.     curSpriteLayerP = spriteWorldP->headSpriteLayerP;
  611.  
  612.     while (curSpriteLayerP != NULL)
  613.     {
  614.         SWUnlockSpriteLayer(curSpriteLayerP);
  615.  
  616.         curSpriteLayerP = curSpriteLayerP->nextSpriteLayerP;
  617.     }
  618. }
  619.  
  620.  
  621. #pragma mark -
  622. ///--------------------------------------------------------------------------------------
  623. //    SWSetPortToBackground
  624. ///--------------------------------------------------------------------------------------
  625.  
  626. SW_FUNC void SWSetPortToBackground(
  627.     SpriteWorldPtr    spriteWorldP)
  628. {
  629.     SW_ASSERT(spriteWorldP != NULL);
  630.     SW_ASSERT(spriteWorldP->backFrameP->isFrameLocked);
  631.     
  632.     if ( spriteWorldP->backFrameP->isFrameLocked )
  633.         SetGWorld(spriteWorldP->backFrameP->framePort, nil);
  634. }
  635.  
  636.  
  637. ///--------------------------------------------------------------------------------------
  638. //    SWSetPortToWorkArea
  639. ///--------------------------------------------------------------------------------------
  640.  
  641. SW_FUNC void SWSetPortToWorkArea(
  642.     SpriteWorldPtr    spriteWorldP)
  643. {
  644.     SW_ASSERT(spriteWorldP != NULL);
  645.     SW_ASSERT(spriteWorldP->workFrameP->isFrameLocked);
  646.     
  647.     if ( spriteWorldP->workFrameP->isFrameLocked )
  648.         SetGWorld(spriteWorldP->workFrameP->framePort, nil);
  649. }
  650.  
  651.  
  652. ///--------------------------------------------------------------------------------------
  653. //    SWSetPortToWindow
  654. ///--------------------------------------------------------------------------------------
  655.  
  656. SW_FUNC void SWSetPortToWindow(
  657.     SpriteWorldPtr    spriteWorldP)
  658. {
  659.     SW_ASSERT(spriteWorldP != NULL);
  660.     
  661.     SetGWorld(spriteWorldP->windowFrameP->framePort, nil);
  662. }
  663.  
  664.  
  665. ///--------------------------------------------------------------------------------------
  666. //    SWSetSpriteWorldOffscreenDrawProc
  667. ///--------------------------------------------------------------------------------------
  668.  
  669. SW_FUNC OSErr SWSetSpriteWorldOffscreenDrawProc(
  670.     SpriteWorldPtr    spriteWorldP,
  671.     DrawProcPtr        drawProc)
  672. {
  673.     OSErr    err = noErr;
  674.     
  675.     SW_ASSERT(spriteWorldP != NULL);
  676.     
  677.     if (spriteWorldP->pixelDepth != 8)
  678.     {
  679.         if ( drawProc == BlitPixie8BitRectDrawProc || 
  680.              drawProc == BP8BitInterlacedRectDrawProc )
  681.             err = kWrongDepthErr;
  682.     }
  683.  
  684.     if ( err == noErr )
  685.         spriteWorldP->offscreenDrawProc = drawProc;
  686.     
  687.     SWSetStickyIfError( err );
  688.     return err;
  689. }
  690.  
  691.  
  692. ///--------------------------------------------------------------------------------------
  693. //    SWSetSpriteWorldScreenDrawProc
  694. ///--------------------------------------------------------------------------------------
  695.  
  696. SW_FUNC OSErr SWSetSpriteWorldScreenDrawProc(
  697.     SpriteWorldPtr    spriteWorldP,
  698.     DrawProcPtr        drawProc)
  699. {
  700.     OSErr    err = noErr;
  701.     
  702.     SW_ASSERT(spriteWorldP != NULL);
  703.     
  704.     if (drawProc == NULL)
  705.         err = kNilParameterErr;
  706.     
  707.     if ( (*spriteWorldP->windowFrameP->framePort->portPixMap)->pixelSize != 8 ||
  708.         (*spriteWorldP->windowFrameP->framePort->portPixMap)->pixelSize !=
  709.          spriteWorldP->pixelDepth )
  710.     {
  711.         if ( drawProc == BlitPixie8BitRectDrawProc || 
  712.              drawProc == BP8BitInterlacedRectDrawProc )
  713.             err = kWrongDepthErr;
  714.     }
  715.  
  716.     if ( err == noErr )
  717.         spriteWorldP->screenDrawProc = drawProc;
  718.         
  719.     SWSetStickyIfError( err );
  720.     return err;
  721. }
  722.  
  723.  
  724. ///--------------------------------------------------------------------------------------
  725. //    SWSetPostEraseCallBack
  726. ///--------------------------------------------------------------------------------------
  727.  
  728. SW_FUNC void SWSetPostEraseCallBack(
  729.     SpriteWorldPtr    spriteWorldP,
  730.     CallBackPtr        callBack)
  731. {
  732.     spriteWorldP->postEraseCallBack = callBack;
  733. }
  734.  
  735.  
  736. ///--------------------------------------------------------------------------------------
  737. //    SWSetPostDrawCallBack
  738. ///--------------------------------------------------------------------------------------
  739.  
  740. SW_FUNC void SWSetPostDrawCallBack(
  741.     SpriteWorldPtr    spriteWorldP,
  742.     CallBackPtr        callBack)
  743. {
  744.     spriteWorldP->postDrawCallBack = callBack;
  745. }
  746.  
  747.  
  748. ///--------------------------------------------------------------------------------------
  749. //    SWStdWorldDrawProc
  750. ///--------------------------------------------------------------------------------------
  751.  
  752. SW_FUNC void SWStdWorldDrawProc(
  753.     FramePtr    srcFrameP,
  754.     FramePtr    dstFrameP,
  755.     Rect*        srcRect,
  756.     Rect*        dstRect)
  757. {    
  758.     Rect    srcCopyBitsRect = *srcRect;
  759.     Rect    dstCopyBitsRect = *dstRect;
  760.     
  761.     
  762.         // clip off the top
  763.     if (dstCopyBitsRect.top < dstFrameP->frameRect.top)
  764.     {
  765.         srcCopyBitsRect.top += dstFrameP->frameRect.top - dstCopyBitsRect.top;
  766.         dstCopyBitsRect.top =  dstFrameP->frameRect.top;
  767.         if (dstCopyBitsRect.top >= dstCopyBitsRect.bottom) return;
  768.     }
  769.         // clip off the bottom
  770.     if (dstCopyBitsRect.bottom > dstFrameP->frameRect.bottom)
  771.     {
  772.         srcCopyBitsRect.bottom -= dstCopyBitsRect.bottom - dstFrameP->frameRect.bottom;
  773.         dstCopyBitsRect.bottom = dstFrameP->frameRect.bottom;
  774.         if (dstCopyBitsRect.bottom <= dstCopyBitsRect.top) return;
  775.     }
  776.         // clip off the left
  777.     if (dstCopyBitsRect.left < dstFrameP->frameRect.left)
  778.     {
  779.         srcCopyBitsRect.left += dstFrameP->frameRect.left - dstCopyBitsRect.left;
  780.         dstCopyBitsRect.left = dstFrameP->frameRect.left;
  781.         if (dstCopyBitsRect.left >= dstCopyBitsRect.right) 
  782.             return;
  783.     }
  784.         // clip off the right
  785.     if (dstCopyBitsRect.right > dstFrameP->frameRect.right)
  786.     {
  787.         srcCopyBitsRect.right -= dstCopyBitsRect.right - dstFrameP->frameRect.right;
  788.         dstCopyBitsRect.right = dstFrameP->frameRect.right;
  789.         if (dstCopyBitsRect.right <= dstCopyBitsRect.left) return;
  790.     }
  791.             
  792.     CopyBits( (BitMap*)srcFrameP->framePix,
  793.         (BitMap*)dstFrameP->framePix,
  794.         &srcCopyBitsRect,
  795.         &dstCopyBitsRect,
  796.         srcCopy, NULL);
  797. }
  798.  
  799.  
  800. ///--------------------------------------------------------------------------------------
  801. //    SWCopyBackgroundToWorkArea
  802. ///--------------------------------------------------------------------------------------
  803.  
  804. SW_FUNC void SWCopyBackgroundToWorkArea(
  805.     SpriteWorldPtr spriteWorldP)
  806. {        
  807.     GWorldPtr        holdGWorld;
  808.     GDHandle        holdGDH;
  809.     
  810.     SW_ASSERT(spriteWorldP != NULL);
  811.     SW_ASSERT(spriteWorldP->backFrameP->isFrameLocked);
  812.     SW_ASSERT(spriteWorldP->workFrameP->isFrameLocked);
  813.     
  814.     GetGWorld( &holdGWorld, &holdGDH );
  815.     
  816.         // Copy the background frame into the work area
  817.     
  818.     SetGWorld(spriteWorldP->workFrameP->framePort, nil);
  819.     (*spriteWorldP->offscreenDrawProc)(spriteWorldP->backFrameP,
  820.                                 spriteWorldP->workFrameP,
  821.                                 &spriteWorldP->backFrameP->frameRect,
  822.                                 &spriteWorldP->workFrameP->frameRect);
  823.     
  824.     SetGWorld( holdGWorld, holdGDH );
  825. }
  826.  
  827.  
  828. ///--------------------------------------------------------------------------------------
  829. //    SWChangeWorldRect
  830. ///--------------------------------------------------------------------------------------
  831.  
  832. SW_FUNC OSErr SWChangeWorldRect(
  833.     SpriteWorldPtr spriteWorldP, 
  834.     Rect* newWorldRectP,
  835.     Boolean changeOffscreenAreas)
  836. {
  837.     Rect        oldWindRect;
  838.     short        hChange, vChange;
  839.     OSErr        err = noErr;
  840.     
  841.     SW_ASSERT(spriteWorldP != NULL && newWorldRectP != NULL);
  842.     
  843.         // Report error if newWorldRectP is larger than the size of the offscreen areas
  844.     if ( SW_RECT_WIDTH((*newWorldRectP)) > SW_RECT_WIDTH(spriteWorldP->originalBackRect) ||
  845.          SW_RECT_HEIGHT((*newWorldRectP)) > SW_RECT_HEIGHT(spriteWorldP->originalBackRect) )
  846.     {
  847.         err = kOutOfRangeErr;
  848.     }
  849.         
  850.     
  851.     if (err == noErr)
  852.     {
  853.             // Now we calculate the difference in size of old and new windRect
  854.         oldWindRect = spriteWorldP->windRect;
  855.         hChange = (oldWindRect.right - oldWindRect.left) - 
  856.                     (newWorldRectP->right - newWorldRectP->left);
  857.         vChange = (oldWindRect.bottom - oldWindRect.top) - 
  858.                     (newWorldRectP->bottom - newWorldRectP->top);
  859.         
  860.             // Change the windRect
  861.         spriteWorldP->windRect = *newWorldRectP;
  862.         
  863.             // Resize the visScrollRect
  864.         SWResizeVisScrollRect(spriteWorldP,
  865.                 newWorldRectP->right - newWorldRectP->left, 
  866.                 newWorldRectP->bottom - newWorldRectP->top);
  867.         
  868.         if (changeOffscreenAreas)
  869.         {
  870.                 // Make offscreen areas think they are the same size as the new windRect
  871.             spriteWorldP->workFrameP->frameRect.bottom -= vChange;
  872.             spriteWorldP->workFrameP->frameRect.right -= hChange;
  873.             spriteWorldP->backFrameP->frameRect.bottom -= vChange;
  874.             spriteWorldP->backFrameP->frameRect.right -= hChange;
  875.             
  876.                 // Update backRect as well
  877.             spriteWorldP->backRect.bottom -= vChange;
  878.             spriteWorldP->backRect.right -= hChange;
  879.         }
  880.         
  881.             // Recalculate blitter data based on new windRect position
  882.         SWWindowMoved(spriteWorldP);
  883.     }
  884.     
  885.     return err;
  886. }
  887.  
  888.  
  889. ///--------------------------------------------------------------------------------------
  890. //    SWRestoreWorldRect
  891. ///--------------------------------------------------------------------------------------
  892.  
  893. SW_FUNC void SWRestoreWorldRect(SpriteWorldPtr spriteWorldP)
  894. {
  895.     Rect    originalWindRect = spriteWorldP->originalWindRect;
  896.     
  897.     SW_ASSERT(spriteWorldP != NULL);
  898.     
  899.         // Restore everything to its original size
  900.     spriteWorldP->windRect = originalWindRect;
  901.     spriteWorldP->workFrameP->frameRect = spriteWorldP->originalBackRect;
  902.     spriteWorldP->backFrameP->frameRect = spriteWorldP->originalBackRect;
  903.     spriteWorldP->backRect = spriteWorldP->originalBackRect;
  904.     
  905.         // Resize the visScrollRect to match the originalWindRect
  906.     SWResizeVisScrollRect(spriteWorldP,
  907.             originalWindRect.right - originalWindRect.left, 
  908.             originalWindRect.bottom - originalWindRect.top);
  909.     
  910.         // Recalculate blitter data based on new windRect position
  911.     SWWindowMoved(spriteWorldP);
  912. }
  913.  
  914.  
  915. ///--------------------------------------------------------------------------------------
  916. //    SWWindowMoved
  917. ///--------------------------------------------------------------------------------------
  918.  
  919. SW_FUNC void SWWindowMoved(SpriteWorldPtr spriteWorldP)
  920. {
  921.     GDHandle        theGDH,
  922.                     holdGDH;
  923.     GWorldPtr        holdGWorld;
  924.     Rect             worldRect,
  925.                     globalWorldRect,
  926.                     screenRect;
  927.     short            depth;
  928.     long             curScanLine;
  929.     Point            globalOffset;
  930.     
  931.     SW_ASSERT(spriteWorldP != NULL);
  932.     SW_ASSERT(spriteWorldP->windowFrameP->isFrameLocked);
  933.     
  934.     GetGWorld( &holdGWorld, &holdGDH );
  935.     
  936.     SWSetPortToWindow( spriteWorldP );
  937.     theGDH = spriteWorldP->mainSWGDH;
  938.     
  939.     worldRect = spriteWorldP->windRect;
  940.     globalWorldRect = worldRect;
  941.     screenRect = (*theGDH)->gdRect;
  942.     LocalToGlobal( &(topLeft(globalWorldRect)) );
  943.     LocalToGlobal( &(botRight(globalWorldRect)) );
  944.     globalOffset = topLeft(globalWorldRect);
  945.     
  946.         // Clip worldRect with screenRect
  947.     if (globalWorldRect.top < screenRect.top)
  948.         globalWorldRect.top = screenRect.top;
  949.     if (globalWorldRect.bottom > screenRect.bottom)
  950.         globalWorldRect.bottom = screenRect.bottom;
  951.     if (globalWorldRect.left < screenRect.left)
  952.         globalWorldRect.left = screenRect.left;
  953.     if (globalWorldRect.right > screenRect.right)
  954.         globalWorldRect.right = screenRect.right;
  955.     
  956.         // Convert global rect back to local rect
  957.     GlobalToLocal( &(topLeft(globalWorldRect)) );
  958.     GlobalToLocal( &(botRight(globalWorldRect)) );
  959.     
  960.     spriteWorldP->windowFrameP->frameRect = globalWorldRect;
  961.     
  962.     
  963.     // cache frameRowBytes for use by our blitter routine
  964.  
  965.     spriteWorldP->windowFrameP->frameRowBytes = 
  966.             (**spriteWorldP->windowFrameP->framePort->portPixMap).rowBytes & 0x7FFF;
  967.         
  968.     depth = (**(**theGDH).gdPMap).pixelSize;
  969.     
  970.     // align on long word boundary
  971.     spriteWorldP->windowFrameP->rightAlignFactor = 
  972.             ((sizeof(long) * kBitsPerByte) / depth) - 1;
  973.     spriteWorldP->windowFrameP->leftAlignFactor = 
  974.             ~(spriteWorldP->windowFrameP->rightAlignFactor);
  975.     
  976.         
  977.         // set the worldRectOffset
  978.     spriteWorldP->windowFrameP->worldRectOffset = 0;
  979.         
  980.     if (depth < 8)
  981.     {
  982.         short        roundOff;
  983.         
  984.         roundOff = 8/depth;
  985.         spriteWorldP->windowFrameP->worldRectOffset = 
  986.             (globalOffset.h - worldRect.left) - 
  987.             (((globalOffset.h - worldRect.left)/roundOff)*roundOff);
  988.     }
  989.     
  990.         // set up an array of offsets to the scan lines
  991.     for (curScanLine = 0; curScanLine < spriteWorldP->windowFrameP->numScanLines; curScanLine++)
  992.     {
  993.         spriteWorldP->windowFrameP->scanLinePtrArray[curScanLine] = 
  994.             ((curScanLine+(globalOffset.v - worldRect.top) ) * 
  995.             spriteWorldP->windowFrameP->frameRowBytes) +
  996.             (globalOffset.h - worldRect.left)*4/(32/depth);
  997.     }
  998.     
  999.     SetGWorld( holdGWorld, holdGDH );
  1000. }
  1001.  
  1002.  
  1003. ///--------------------------------------------------------------------------------------
  1004. //    SWWindowFrameMoved
  1005. ///--------------------------------------------------------------------------------------
  1006.     
  1007. SW_FUNC void SWWindowFrameMoved(
  1008.     FramePtr windowFrameP,
  1009.     Rect *frameRect)
  1010. {
  1011.     GDHandle        theGDH,
  1012.                     holdGDH;
  1013.     GWorldPtr        theGWorld,
  1014.                     holdGWorld;
  1015.     Rect             worldRect,
  1016.                     globalWorldRect,
  1017.                     screenRect;
  1018.     short            depth;
  1019.     long             curScanLine;
  1020.     Point            globalOffset;
  1021.     
  1022.     SW_ASSERT(windowFrameP != NULL);
  1023.     SW_ASSERT(windowFrameP->isFrameLocked);
  1024.     
  1025.     GetGWorld( &holdGWorld, &holdGDH );
  1026.     
  1027.     SetGWorld(windowFrameP->framePort, nil);
  1028.     GetGWorld(&theGWorld, &theGDH);    // Get the GDH
  1029.     
  1030.     worldRect = *frameRect;
  1031.     globalWorldRect = *frameRect;
  1032.     screenRect = (*theGDH)->gdRect;
  1033.     LocalToGlobal( &(topLeft(globalWorldRect)) );
  1034.     LocalToGlobal( &(botRight(globalWorldRect)) );
  1035.     globalOffset = topLeft(globalWorldRect);
  1036.     
  1037.         // Clip worldRect with screenRect
  1038.     if (globalWorldRect.top < screenRect.top)
  1039.         globalWorldRect.top = screenRect.top;
  1040.     if (globalWorldRect.bottom > screenRect.bottom)
  1041.         globalWorldRect.bottom = screenRect.bottom;
  1042.     if (globalWorldRect.left < screenRect.left)
  1043.         globalWorldRect.left = screenRect.left;
  1044.     if (globalWorldRect.right > screenRect.right)
  1045.         globalWorldRect.right = screenRect.right;
  1046.     
  1047.         // Convert global rect back to local rect
  1048.     GlobalToLocal( &(topLeft(globalWorldRect)) );
  1049.     GlobalToLocal( &(botRight(globalWorldRect)) );
  1050.     
  1051.     windowFrameP->frameRect = globalWorldRect;
  1052.     
  1053.     
  1054.         // cache frameRowBytes for use by our blitter routine
  1055.     windowFrameP->frameRowBytes = (**windowFrameP->framePort->portPixMap).rowBytes & 0x7FFF;
  1056.     depth = (**(**theGDH).gdPMap).pixelSize;
  1057.     
  1058.         // align to long boundary
  1059.     windowFrameP->rightAlignFactor = ((sizeof(long) * kBitsPerByte) / depth) - 1;
  1060.     windowFrameP->leftAlignFactor = ~(windowFrameP->rightAlignFactor);
  1061.     
  1062.         // set the worldRectOffset
  1063.     windowFrameP->worldRectOffset = 0;
  1064.         
  1065.     if (depth < 8)
  1066.     {
  1067.         short        roundOff;
  1068.         
  1069.         roundOff = 8/depth;
  1070.         windowFrameP->worldRectOffset = (globalOffset.h - worldRect.left) - 
  1071.             (((globalOffset.h - worldRect.left)/roundOff)*roundOff);
  1072.     }
  1073.     
  1074.         // set up an array of offsets to the scan lines
  1075.     for (curScanLine = 0; curScanLine < windowFrameP->numScanLines; curScanLine++)
  1076.     {
  1077.         windowFrameP->scanLinePtrArray[curScanLine] = 
  1078.             ((curScanLine+(globalOffset.v - worldRect.top) ) * 
  1079.             windowFrameP->frameRowBytes) + (globalOffset.h - worldRect.left)*4/(32/depth);
  1080.     }
  1081.     
  1082.     SetGWorld( holdGWorld, holdGDH );
  1083. }
  1084.  
  1085.  
  1086. ///--------------------------------------------------------------------------------------
  1087. //    SWUpdateWindow
  1088. ///--------------------------------------------------------------------------------------
  1089.  
  1090. SW_FUNC void SWUpdateWindow(
  1091.     SpriteWorldPtr spriteWorldP)
  1092. {
  1093.     GWorldPtr        holdGWorld;
  1094.     GDHandle        holdGDH;
  1095.     
  1096.     SW_ASSERT(spriteWorldP != NULL);
  1097.     SW_ASSERT(spriteWorldP->workFrameP->isFrameLocked);
  1098.     SW_ASSERT(spriteWorldP->windowFrameP->isFrameLocked);
  1099.     
  1100.     GetGWorld( &holdGWorld, &holdGDH );
  1101.     
  1102.     SetGWorld(spriteWorldP->windowFrameP->framePort, nil);
  1103.     spriteWorldP->numTilesChanged = 0;
  1104.     
  1105.     if ( spriteWorldP->usingVBL )
  1106.     {  
  1107.         spriteWorldP->vblTaskRec.hasVBLFired = false;
  1108.         while ( !spriteWorldP->vblTaskRec.hasVBLFired )
  1109.         {}
  1110.     }
  1111.     
  1112.     (*spriteWorldP->screenDrawProc)(spriteWorldP->workFrameP,
  1113.                                     spriteWorldP->windowFrameP,
  1114.                                     &spriteWorldP->visScrollRect,
  1115.                                     &spriteWorldP->windowFrameP->frameRect);
  1116.                                     
  1117.     SetGWorld( holdGWorld, holdGDH );
  1118. }
  1119.  
  1120.  
  1121. #pragma mark -
  1122. ///--------------------------------------------------------------------------------------
  1123. //    SWUpdateSpriteWorld
  1124. ///--------------------------------------------------------------------------------------
  1125.  
  1126. SW_FUNC void SWUpdateSpriteWorld(
  1127.     SpriteWorldPtr spriteWorldP,
  1128.     Boolean updateWindow)
  1129. {
  1130.     UpdateRectStructPtr            curRectStructP,
  1131.                                 nextRectStructP;
  1132.     register SpriteLayerPtr        curSpriteLayerP;
  1133.     register SpritePtr            curSpriteP;
  1134.     Rect                        tempRect;
  1135.     GWorldPtr                    holdGWorld;
  1136.     GDHandle                    holdGDH;
  1137.     short                        curTileLayer;
  1138.     
  1139.     SW_ASSERT(spriteWorldP != NULL);
  1140.     SW_ASSERT(spriteWorldP->backFrameP->isFrameLocked);
  1141.     SW_ASSERT(spriteWorldP->workFrameP->isFrameLocked);
  1142.     SW_ASSERT(spriteWorldP->windowFrameP->isFrameLocked);
  1143.     
  1144.     GetGWorld( &holdGWorld, &holdGDH );
  1145.     
  1146.  
  1147.         // Copy the background into the work area    
  1148.     SetGWorld(spriteWorldP->workFrameP->framePort, nil);
  1149.     (*spriteWorldP->offscreenDrawProc)(spriteWorldP->backFrameP,
  1150.                                        spriteWorldP->workFrameP,
  1151.                                        &spriteWorldP->backFrameP->frameRect,
  1152.                                        &spriteWorldP->workFrameP->frameRect);
  1153.     
  1154.             // Call the postEraseCallBack
  1155.     if (spriteWorldP->postEraseCallBack != NULL)
  1156.         (*spriteWorldP->postEraseCallBack)(spriteWorldP);
  1157.     
  1158.     
  1159.         // Build the current frame of the animation in the work area
  1160.  
  1161.     curSpriteLayerP = spriteWorldP->headSpriteLayerP;
  1162.     curTileLayer = 0;
  1163.  
  1164.         // iterate through the layers in this world
  1165.     while (curSpriteLayerP != NULL)
  1166.     {
  1167.         curSpriteP = curSpriteLayerP->headSpriteP;
  1168.         
  1169.         if (curSpriteLayerP->tileLayer > curTileLayer)
  1170.             curTileLayer = curSpriteLayerP->tileLayer;
  1171.  
  1172.             // iterate through the sprites in this layer
  1173.         while (curSpriteP != NULL)
  1174.         {
  1175.             SW_ASSERT(curSpriteP->curFrameP->isFrameLocked);
  1176.             
  1177.             curSpriteP->tileDepth = curTileLayer;
  1178.             
  1179.             if (curSpriteP->isVisible)
  1180.             {
  1181.                 gCurrentSpriteBeingDrawn = curSpriteP;
  1182.                 
  1183.                     // draw the sprite in the work area
  1184.                 (*curSpriteP->frameDrawProc)(curSpriteP->curFrameP,
  1185.                                             spriteWorldP->workFrameP,
  1186.                                             &curSpriteP->curFrameP->frameRect,
  1187.                                             &curSpriteP->destFrameRect);
  1188.                 
  1189.                 gCurrentSpriteBeingDrawn = NULL;
  1190.                 
  1191.                 if (spriteWorldP->tilingIsOn &&
  1192.                     curSpriteP->tileDepth <= spriteWorldP->lastActiveTileLayer)
  1193.                 {
  1194.                     tempRect = curSpriteP->destFrameRect;
  1195.                     
  1196.                         // Clip tempRect to visScrollRect
  1197.                     if (tempRect.left < spriteWorldP->visScrollRect.left)
  1198.                         tempRect.left = spriteWorldP->visScrollRect.left;
  1199.                     if (tempRect.right > spriteWorldP->visScrollRect.right)
  1200.                         tempRect.right = spriteWorldP->visScrollRect.right;
  1201.                     if (tempRect.top < spriteWorldP->visScrollRect.top)
  1202.                         tempRect.top = spriteWorldP->visScrollRect.top;
  1203.                     if (tempRect.bottom > spriteWorldP->visScrollRect.bottom)
  1204.                         tempRect.bottom = spriteWorldP->visScrollRect.bottom;
  1205.     
  1206.                     SWDrawTilesAboveSprite(spriteWorldP, &tempRect, curSpriteP->tileDepth);
  1207.                 }
  1208.             
  1209.             }
  1210.             
  1211.                 // set the delta and last rect to the current rect
  1212.             curSpriteP->deltaFrameRect = curSpriteP->destFrameRect;
  1213.             curSpriteP->oldFrameRect = curSpriteP->destFrameRect;
  1214.             
  1215.                 // this sprite no longer needs to be drawn
  1216.             curSpriteP->needsToBeDrawn = false;
  1217.             curSpriteP->needsToBeErased = false;
  1218.  
  1219.             curSpriteP = curSpriteP->nextSpriteP;
  1220.         }
  1221.  
  1222.         curSpriteLayerP = curSpriteLayerP->nextSpriteLayerP;
  1223.     }
  1224.     
  1225.     
  1226.         // Call the postDrawCallBack
  1227.     if (spriteWorldP->postDrawCallBack != NULL)
  1228.         (*spriteWorldP->postDrawCallBack)(spriteWorldP);
  1229.         
  1230.     
  1231.         // Copy the work area into the window
  1232.     if (updateWindow)
  1233.     {
  1234.         SetGWorld(spriteWorldP->windowFrameP->framePort, nil);
  1235.         
  1236.         if ( spriteWorldP->usingVBL )
  1237.         {  
  1238.             spriteWorldP->vblTaskRec.hasVBLFired = false;
  1239.             while ( !spriteWorldP->vblTaskRec.hasVBLFired )
  1240.             {}
  1241.         }
  1242.         
  1243.         (*spriteWorldP->screenDrawProc)(spriteWorldP->workFrameP,
  1244.                                         spriteWorldP->windowFrameP,
  1245.                                         &spriteWorldP->visScrollRect,
  1246.                                         &spriteWorldP->windowFrameP->frameRect);
  1247.     }
  1248.     
  1249.     
  1250.         // dispose of flagged background rects
  1251.     nextRectStructP = spriteWorldP->headUpdateRectP;
  1252.     while ( nextRectStructP != NULL )
  1253.     {
  1254.         curRectStructP = nextRectStructP;
  1255.         nextRectStructP = curRectStructP->nextRectStructP;
  1256.         DisposePtr( (Ptr)curRectStructP );
  1257.     }
  1258.     spriteWorldP->headUpdateRectP = NULL;
  1259.     
  1260.     spriteWorldP->numTilesChanged = 0;
  1261.     
  1262.     SetGWorld( holdGWorld, holdGDH );
  1263. }
  1264.  
  1265.  
  1266. ///--------------------------------------------------------------------------------------
  1267. //    SWProcessSpriteWorld
  1268. ///--------------------------------------------------------------------------------------
  1269.  
  1270. SW_FUNC void SWProcessSpriteWorld(
  1271.     SpriteWorldPtr spriteWorldP)
  1272. {
  1273.     UnsignedWide                curMicroseconds;
  1274.     register unsigned long        millisecDifference;
  1275.     register SpriteLayerPtr        curSpriteLayerP;
  1276.     register SpritePtr            curSpriteP, nextSpriteP;
  1277.     register FramePtr            newFrameP;
  1278.     
  1279.     SW_ASSERT(spriteWorldP != NULL);
  1280.     
  1281.     Microseconds( &curMicroseconds );
  1282.         // has hi long has rolled over?
  1283.     if ( curMicroseconds.hi > spriteWorldP->lastMicroseconds.hi )
  1284.     {
  1285.         millisecDifference = 
  1286.             (0xffffffff - (spriteWorldP->lastMicroseconds.lo - curMicroseconds.lo))/1000;
  1287.     }
  1288.     else
  1289.     {
  1290.         millisecDifference = (curMicroseconds.lo - spriteWorldP->lastMicroseconds.lo)/1000;
  1291.     }
  1292.     if ( millisecDifference > 0 )
  1293.     {
  1294.         spriteWorldP->runningTimeCount += millisecDifference;
  1295.         spriteWorldP->lastMicroseconds.lo = curMicroseconds.lo;
  1296.         spriteWorldP->lastMicroseconds.hi = curMicroseconds.hi;
  1297.     }
  1298.  
  1299.     if ( (spriteWorldP->runningTimeCount - spriteWorldP->timeOfLastFrame >= 
  1300.                 spriteWorldP->fpsTimeInterval) )
  1301.     {
  1302.         spriteWorldP->frameHasOccurred = true;
  1303.         spriteWorldP->timeOfLastFrame = spriteWorldP->runningTimeCount;
  1304.     }
  1305.     else
  1306.     {
  1307.         spriteWorldP->frameHasOccurred = false;
  1308.         return;
  1309.     }
  1310.  
  1311.     if ( spriteWorldP->deadSpriteLayerP->headSpriteP != NULL )
  1312.     {
  1313.         SWFindSpritesToBeRemoved( spriteWorldP );
  1314.     }
  1315.     
  1316.         // Call the tileChangeProc, if there is one
  1317.     if (spriteWorldP->tileChangeProc != NULL)
  1318.     {
  1319.         (*spriteWorldP->tileChangeProc)(spriteWorldP);
  1320.     }
  1321.     
  1322.     curSpriteLayerP = spriteWorldP->headSpriteLayerP;    
  1323.     
  1324.         // iterate through the layers in this world
  1325.     while (curSpriteLayerP != NULL)
  1326.     {
  1327.         if (!curSpriteLayerP->isPaused)
  1328.         {
  1329.             curSpriteP = curSpriteLayerP->headSpriteP;
  1330.             
  1331.                 // iterate through the sprites in this layer
  1332.             while (curSpriteP != NULL)
  1333.             {            
  1334.                 SW_ASSERT(curSpriteP->curFrameP->isFrameLocked);
  1335.                 nextSpriteP = curSpriteP->nextSpriteP;
  1336.                 
  1337.                     // is it time to advance the sprite’s frame?
  1338.                 if ( curSpriteP->frameTimeInterval >= 0 && 
  1339.                     (spriteWorldP->runningTimeCount - curSpriteP->timeOfLastFrameChange > 
  1340.                     curSpriteP->frameTimeInterval) )
  1341.                 {
  1342.                     register long        currentFrameIndex;
  1343.                     
  1344.                     
  1345.                     curSpriteP->timeOfLastFrameChange = spriteWorldP->runningTimeCount;
  1346.                     
  1347.                     currentFrameIndex  = curSpriteP->curFrameIndex;
  1348.                     currentFrameIndex += curSpriteP->frameAdvance;
  1349.                     
  1350.                     if (currentFrameIndex < curSpriteP->firstFrameIndex)
  1351.                     {
  1352.                         if (curSpriteP->frameAdvanceMode == kSWWrapAroundMode)
  1353.                         {
  1354.                                 // wrap to the last frame
  1355.                             currentFrameIndex = curSpriteP->lastFrameIndex;
  1356.                         }
  1357.                         else    // curSpriteP->frameAdvanceMode == kSWPatrollingMode
  1358.                         {
  1359.                                 // change direction and set index to what it should be
  1360.                             curSpriteP->frameAdvance = -curSpriteP->frameAdvance;
  1361.                             currentFrameIndex += curSpriteP->frameAdvance;
  1362.                             currentFrameIndex += curSpriteP->frameAdvance;
  1363.                         }
  1364.                     }
  1365.                     else if (currentFrameIndex > curSpriteP->lastFrameIndex)
  1366.                     {
  1367.                         if (curSpriteP->frameAdvanceMode == kSWWrapAroundMode)
  1368.                         {
  1369.                                 // wrap to the first frame
  1370.                             currentFrameIndex = curSpriteP->firstFrameIndex;
  1371.                         }
  1372.                         else    // curSpriteP->frameAdvanceMode == kSWPatrollingMode
  1373.                         {
  1374.                                 // change direction and set index to what it should be
  1375.                             curSpriteP->frameAdvance = -curSpriteP->frameAdvance;
  1376.                             currentFrameIndex += curSpriteP->frameAdvance;
  1377.                             currentFrameIndex += curSpriteP->frameAdvance;
  1378.                         }
  1379.                     }
  1380.                     
  1381.                     curSpriteP->curFrameIndex = currentFrameIndex;
  1382.                     
  1383.                     
  1384.                         // is there a frame callback?
  1385.                     if (curSpriteP->frameChangeProc != NULL)
  1386.                     {
  1387.                              // get new frame
  1388.                         newFrameP =    curSpriteP->frameArray[currentFrameIndex];
  1389.                         
  1390.                             // call it
  1391.                         (*curSpriteP->frameChangeProc)(curSpriteP, newFrameP,
  1392.                                 &curSpriteP->curFrameIndex);
  1393.                         
  1394.                             // make sure the new frame index is in range
  1395.                         if (curSpriteP->curFrameIndex < 0)
  1396.                         {
  1397.                             curSpriteP->curFrameIndex = 0;
  1398.                         }
  1399.                         else if (curSpriteP->curFrameIndex >= curSpriteP->maxFrames)
  1400.                         {
  1401.                             curSpriteP->curFrameIndex = curSpriteP->maxFrames - 1;
  1402.                         }
  1403.                     }
  1404.                     
  1405.                         // change the frame
  1406.                     newFrameP =    curSpriteP->frameArray[curSpriteP->curFrameIndex];
  1407.                     
  1408.                         // has the frame actually changed?
  1409.                     if (curSpriteP->curFrameP != newFrameP)
  1410.                     {
  1411.                         SWSetCurrentFrameIndex(curSpriteP, curSpriteP->curFrameIndex);
  1412.                     }
  1413.                 }
  1414.                 
  1415.                     // is it time to move the sprite?
  1416.                 if ( curSpriteP->moveTimeInterval >= 0 && 
  1417.                     (spriteWorldP->runningTimeCount - curSpriteP->timeOfLastMove) > 
  1418.                     curSpriteP->moveTimeInterval )
  1419.                 {
  1420.                     curSpriteP->timeOfLastMove = spriteWorldP->runningTimeCount;
  1421.                     
  1422.                         // is there a movement callback?
  1423.                     if (curSpriteP->spriteMoveProc != NULL)
  1424.                     {
  1425.                         (*curSpriteP->spriteMoveProc)(curSpriteP);
  1426.                     }
  1427.                 }
  1428.                 curSpriteP = nextSpriteP;
  1429.             }
  1430.         }
  1431.         curSpriteLayerP = curSpriteLayerP->nextSpriteLayerP;
  1432.     }
  1433. }
  1434.  
  1435.  
  1436. ///--------------------------------------------------------------------------------------
  1437. //    SWAnimateSpriteWorld
  1438. ///--------------------------------------------------------------------------------------
  1439.  
  1440. SW_FUNC void SWAnimateSpriteWorld(
  1441.     SpriteWorldPtr spriteWorldP)
  1442. {
  1443.     UpdateRectStructPtr            curRectStructP,
  1444.                                 nextRectStructP;
  1445.     register SpriteLayerPtr     curSpriteLayerP;
  1446.     register SpritePtr             curSpriteP;
  1447.     SpritePtr                     headActiveSpriteP = NULL;    // Tail of active sprite list
  1448.     SpritePtr                    headIdleSpriteP = NULL;        // Tail of idle sprite list
  1449.     SpritePtr                     curActiveSpriteP = NULL;
  1450.     SpritePtr                     curIdleSpriteP = NULL;
  1451.     Rect                        screenDestRect;
  1452.     Rect                        *changedRectP;
  1453.     short                        index, curTileLayer;
  1454.  
  1455.     SW_ASSERT(spriteWorldP != NULL);
  1456.     SW_ASSERT(spriteWorldP->backFrameP->isFrameLocked);
  1457.     SW_ASSERT(spriteWorldP->workFrameP->isFrameLocked);
  1458.     SW_ASSERT(spriteWorldP->windowFrameP->isFrameLocked);
  1459.     
  1460.     if (!spriteWorldP->frameHasOccurred)
  1461.         return;
  1462.     
  1463.         // Add the deadSpriteLayer if there are any Sprites in it.
  1464.     if ( spriteWorldP->deadSpriteLayerP->headSpriteP != NULL )
  1465.     {
  1466.         SWAddSpriteLayer(spriteWorldP, spriteWorldP->deadSpriteLayerP);
  1467.     }
  1468.     
  1469.         // the current port should be the one in which we are drawing    
  1470.     SetGWorld(spriteWorldP->workFrameP->framePort, nil);
  1471.     
  1472.     //-----------------erase the sprites--------------------
  1473.     
  1474.     curSpriteLayerP = spriteWorldP->headSpriteLayerP;
  1475.     curTileLayer = 0;
  1476.     
  1477.         // iterate through the layers in this world
  1478.     while (curSpriteLayerP != NULL)
  1479.     {
  1480.         curSpriteP = curSpriteLayerP->headSpriteP;
  1481.         
  1482.         if (curSpriteLayerP->tileLayer > curTileLayer)
  1483.             curTileLayer = curSpriteLayerP->tileLayer;
  1484.         
  1485.             // iterate through the sprites in this layer
  1486.         while (curSpriteP != NULL)
  1487.         {
  1488.             SW_ASSERT(curSpriteP->curFrameP->isFrameLocked);
  1489.             curSpriteP->tileDepth = curTileLayer;
  1490.             
  1491.             if ((curSpriteP->needsToBeDrawn && curSpriteP->isVisible) ||
  1492.                 (curSpriteP->needsToBeErased && !curSpriteP->isVisible))
  1493.             {
  1494.                     // Add sprite to active sprite list
  1495.                 if (headActiveSpriteP == NULL)
  1496.                     headActiveSpriteP = curSpriteP;
  1497.                 
  1498.                 if (curActiveSpriteP != NULL)
  1499.                         curActiveSpriteP->nextActiveSpriteP = curSpriteP;
  1500.                 
  1501.                 curActiveSpriteP = curSpriteP;
  1502.                 
  1503.                     // union last rect and current rect
  1504.                     // this way is much faster than UnionRect
  1505.                 curSpriteP->deltaFrameRect.top =
  1506.                     SW_MIN(curSpriteP->oldFrameRect.top, curSpriteP->destFrameRect.top);
  1507.                 curSpriteP->deltaFrameRect.left =
  1508.                     SW_MIN(curSpriteP->oldFrameRect.left, curSpriteP->destFrameRect.left);
  1509.                 curSpriteP->deltaFrameRect.bottom =
  1510.                     SW_MAX(curSpriteP->oldFrameRect.bottom, curSpriteP->destFrameRect.bottom);
  1511.                 curSpriteP->deltaFrameRect.right =
  1512.                     SW_MAX(curSpriteP->oldFrameRect.right, curSpriteP->destFrameRect.right);
  1513.                 {
  1514.                     short temp;
  1515.                     
  1516.                         // align the left edge to long word boundary
  1517.                     curSpriteP->deltaFrameRect.left &=
  1518.                             (spriteWorldP->workFrameP->leftAlignFactor);
  1519.                     
  1520.                         // align the right edge to long word boundary
  1521.                     temp = curSpriteP->deltaFrameRect.right &
  1522.                         spriteWorldP->workFrameP->rightAlignFactor;
  1523.                     if (temp != 0)
  1524.                     {
  1525.                         curSpriteP->deltaFrameRect.right +=
  1526.                                 (spriteWorldP->workFrameP->rightAlignFactor + 1) - temp;
  1527.                     }
  1528.                     
  1529.                         // align the left edge to long word boundary
  1530.                     curSpriteP->oldFrameRect.left &=
  1531.                         (spriteWorldP->workFrameP->leftAlignFactor);
  1532.                     
  1533.                         // align the right edge to long word boundary
  1534.                     temp = curSpriteP->oldFrameRect.right &
  1535.                         spriteWorldP->workFrameP->rightAlignFactor;
  1536.                     if (temp != 0)
  1537.                     {
  1538.                         curSpriteP->oldFrameRect.right +=
  1539.                             (spriteWorldP->workFrameP->rightAlignFactor + 1) - temp;
  1540.                     }
  1541.                 }
  1542.                 
  1543.                     // copy the back drop piece
  1544.                 (*spriteWorldP->offscreenDrawProc)(
  1545.                         spriteWorldP->backFrameP,
  1546.                         spriteWorldP->workFrameP,
  1547.                         &curSpriteP->oldFrameRect,
  1548.                         &curSpriteP->oldFrameRect);
  1549.             }
  1550.             else if (curSpriteP->isVisible)
  1551.             {
  1552.                     // Add sprite to idle sprite list
  1553.                 if (headIdleSpriteP == NULL)
  1554.                     headIdleSpriteP = curSpriteP;
  1555.                 
  1556.                 if (curIdleSpriteP != NULL)
  1557.                     curIdleSpriteP->nextIdleSpriteP = curSpriteP;
  1558.                 
  1559.                 curIdleSpriteP = curSpriteP;
  1560.             }
  1561.             
  1562.             curSpriteP = curSpriteP->nextSpriteP;
  1563.         }
  1564.         
  1565.         curSpriteLayerP = curSpriteLayerP->nextSpriteLayerP;    
  1566.     }
  1567.     
  1568.     if (curActiveSpriteP != NULL)
  1569.         curActiveSpriteP->nextActiveSpriteP = NULL;
  1570.     
  1571.     if (curIdleSpriteP != NULL)
  1572.         curIdleSpriteP->nextIdleSpriteP = NULL;
  1573.     
  1574.     
  1575.         // update flagged background rects
  1576.     curRectStructP = spriteWorldP->headUpdateRectP;
  1577.     while ( curRectStructP != NULL )
  1578.     {
  1579.         (*spriteWorldP->offscreenDrawProc)(
  1580.                         spriteWorldP->backFrameP,
  1581.                         spriteWorldP->workFrameP,
  1582.                         &curRectStructP->updateRect,
  1583.                         &curRectStructP->updateRect);
  1584.         curRectStructP = curRectStructP->nextRectStructP;
  1585.     }
  1586.     
  1587.         // Redraw idle sprites that were erased by a tile
  1588.     if (spriteWorldP->numTilesChanged > 0)
  1589.         SWCheckIdleSpritesWithTiles(spriteWorldP, headIdleSpriteP);
  1590.  
  1591.         // Redraw idle sprites that were erased by an updateRect
  1592.     if (spriteWorldP->headUpdateRectP != NULL)
  1593.         SWCheckIdleSpritesWithRects(spriteWorldP, headIdleSpriteP);
  1594.  
  1595.         // Call the postEraseCallBack
  1596.     if (spriteWorldP->postEraseCallBack != NULL)
  1597.         (*spriteWorldP->postEraseCallBack)(spriteWorldP);
  1598.     
  1599.     
  1600.     //-----------------draw the sprites--------------------
  1601.     
  1602.     curSpriteLayerP = spriteWorldP->headSpriteLayerP;
  1603.     
  1604.         // iterate through the layers in this world
  1605.     while (curSpriteLayerP != NULL)
  1606.     {
  1607.         curSpriteP = curSpriteLayerP->headSpriteP;
  1608.         
  1609.             // iterate through the sprites in this layer
  1610.         while (curSpriteP != NULL)
  1611.         {
  1612.             if (curSpriteP->isVisible)
  1613.             {
  1614.                 if (curSpriteP->needsToBeDrawn)
  1615.                 {
  1616.                     gCurrentSpriteBeingDrawn = curSpriteP;
  1617.                     
  1618.                         // draw the sprite in the work area
  1619.                     (*curSpriteP->frameDrawProc)(
  1620.                             curSpriteP->curFrameP,
  1621.                             spriteWorldP->workFrameP,
  1622.                             &curSpriteP->curFrameP->frameRect,
  1623.                             &curSpriteP->destFrameRect);
  1624.                             
  1625.                     gCurrentSpriteBeingDrawn = NULL;
  1626.                     
  1627.                     if (spriteWorldP->tilingIsOn &&
  1628.                         curSpriteP->tileDepth <= spriteWorldP->lastActiveTileLayer)
  1629.                     {
  1630.                         screenDestRect = curSpriteP->destFrameRect;
  1631.                         
  1632.                             // Clip screenDestRect to visScrollRect
  1633.                         if (screenDestRect.left < spriteWorldP->visScrollRect.left)
  1634.                             screenDestRect.left = spriteWorldP->visScrollRect.left;
  1635.                         if (screenDestRect.right > spriteWorldP->visScrollRect.right)
  1636.                             screenDestRect.right = spriteWorldP->visScrollRect.right;
  1637.                         if (screenDestRect.top < spriteWorldP->visScrollRect.top)
  1638.                             screenDestRect.top = spriteWorldP->visScrollRect.top;
  1639.                         if (screenDestRect.bottom > spriteWorldP->visScrollRect.bottom)
  1640.                             screenDestRect.bottom = spriteWorldP->visScrollRect.bottom;
  1641.         
  1642.                         SWDrawTilesAboveSprite(spriteWorldP, &screenDestRect, curSpriteP->tileDepth);
  1643.                     }
  1644.                 }
  1645.                 else
  1646.                 {
  1647.                     SWCheckIdleSpriteOverlap(spriteWorldP, curSpriteP, headActiveSpriteP);
  1648.                 }
  1649.             }
  1650.             
  1651.             curSpriteP = curSpriteP->nextSpriteP;
  1652.         }
  1653.         
  1654.         curSpriteLayerP = curSpriteLayerP->nextSpriteLayerP;
  1655.     }
  1656.     
  1657.     
  1658.          // Call the postDrawCallBack
  1659.     if (spriteWorldP->postDrawCallBack != NULL)
  1660.         (*spriteWorldP->postDrawCallBack)(spriteWorldP);
  1661.     
  1662.     
  1663.     //-----------------update the screen--------------------
  1664.     
  1665.         // the current port should be the one in which we are drawing    
  1666.     SetGWorld(spriteWorldP->windowFrameP->framePort, nil);
  1667.     
  1668.         // wait for the VBL
  1669.     if ( spriteWorldP->usingVBL )
  1670.     {  
  1671.         spriteWorldP->vblTaskRec.hasVBLFired = false;
  1672.         while ( !spriteWorldP->vblTaskRec.hasVBLFired )
  1673.         {}
  1674.     }
  1675.     
  1676.     curSpriteP = headActiveSpriteP;
  1677.     
  1678.         // Has a custom worldRect been used? (If so, sprites need offsetting)
  1679.     if (spriteWorldP->windRect.left || spriteWorldP->windRect.top)
  1680.     {
  1681.             // update flagged background rects
  1682.         curRectStructP = spriteWorldP->headUpdateRectP;
  1683.         while ( curRectStructP != NULL )
  1684.         {
  1685.             screenDestRect = curRectStructP->updateRect;
  1686.             screenDestRect.left += spriteWorldP->windRect.left;
  1687.             screenDestRect.right += spriteWorldP->windRect.left;
  1688.             screenDestRect.top += spriteWorldP->windRect.top;
  1689.             screenDestRect.bottom += spriteWorldP->windRect.top;
  1690.             (*spriteWorldP->screenDrawProc)(
  1691.                             spriteWorldP->workFrameP,
  1692.                             spriteWorldP->windowFrameP,
  1693.                             &curRectStructP->updateRect,
  1694.                             &screenDestRect);                        
  1695.             curRectStructP = curRectStructP->nextRectStructP;
  1696.         }
  1697.         
  1698.             // Update on screen the tiles that have changed
  1699.         changedRectP = spriteWorldP->changedTiles;
  1700.         for (index = 0; index < spriteWorldP->numTilesChanged; index++, changedRectP++)
  1701.         {
  1702.             screenDestRect = *changedRectP;
  1703.             
  1704.                 // offset dest rect for screen
  1705.             screenDestRect.left += spriteWorldP->windRect.left;
  1706.             screenDestRect.right += spriteWorldP->windRect.left;
  1707.             screenDestRect.top += spriteWorldP->windRect.top;
  1708.             screenDestRect.bottom += spriteWorldP->windRect.top;
  1709.             
  1710.             (*spriteWorldP->screenDrawProc)(spriteWorldP->workFrameP,
  1711.                     spriteWorldP->windowFrameP, changedRectP, &screenDestRect);
  1712.         }
  1713.         
  1714.         
  1715.             // update the sprites on the screen
  1716.         while (curSpriteP != NULL)
  1717.         {    
  1718.                 // offset the sprite's delta rect for the screen
  1719.             screenDestRect = curSpriteP->deltaFrameRect;
  1720.             
  1721.             screenDestRect.left += spriteWorldP->windRect.left;
  1722.             screenDestRect.right += spriteWorldP->windRect.left;
  1723.             screenDestRect.top += spriteWorldP->windRect.top;
  1724.             screenDestRect.bottom += spriteWorldP->windRect.top;
  1725.             
  1726.             (*spriteWorldP->screenDrawProc)(
  1727.                     spriteWorldP->workFrameP,
  1728.                     spriteWorldP->windowFrameP,
  1729.                     &curSpriteP->deltaFrameRect,
  1730.                     &screenDestRect);
  1731.             
  1732.             
  1733.                 // set the delta and last rect to the current rect
  1734.             curSpriteP->deltaFrameRect = curSpriteP->destFrameRect;
  1735.             curSpriteP->oldFrameRect = curSpriteP->destFrameRect;
  1736.             
  1737.                 // this sprite no longer needs to be drawn
  1738.             curSpriteP->needsToBeDrawn = false;
  1739.             curSpriteP->needsToBeErased = false;
  1740.             
  1741.             curSpriteP = curSpriteP->nextActiveSpriteP;
  1742.         }
  1743.     }
  1744.     else
  1745.     {
  1746.             // update flagged background rects
  1747.         curRectStructP = spriteWorldP->headUpdateRectP;
  1748.         while ( curRectStructP != NULL )
  1749.         {
  1750.             (*spriteWorldP->screenDrawProc)(
  1751.                             spriteWorldP->workFrameP,
  1752.                             spriteWorldP->windowFrameP,
  1753.                             &curRectStructP->updateRect,
  1754.                             &curRectStructP->updateRect);                        
  1755.             curRectStructP = curRectStructP->nextRectStructP;
  1756.         }
  1757.         
  1758.             // Update on screen the tiles that have changed
  1759.         changedRectP = spriteWorldP->changedTiles;
  1760.         for (index = 0; index < spriteWorldP->numTilesChanged; index++, changedRectP++)
  1761.         {
  1762.             (*spriteWorldP->screenDrawProc)(spriteWorldP->workFrameP,
  1763.                     spriteWorldP->windowFrameP, changedRectP, changedRectP);
  1764.         }
  1765.     
  1766.         
  1767.             // update the sprites on the screen
  1768.         while (curSpriteP != NULL)
  1769.         {    
  1770.             (*spriteWorldP->screenDrawProc)(
  1771.                     spriteWorldP->workFrameP,
  1772.                     spriteWorldP->windowFrameP,
  1773.                     &curSpriteP->deltaFrameRect,
  1774.                     &curSpriteP->deltaFrameRect);
  1775.             
  1776.             
  1777.                 // set the delta and last rect to the current rect
  1778.             curSpriteP->deltaFrameRect = curSpriteP->destFrameRect;
  1779.             curSpriteP->oldFrameRect = curSpriteP->destFrameRect;
  1780.             
  1781.                 // this sprite no longer needs to be drawn
  1782.             curSpriteP->needsToBeDrawn = false;
  1783.             curSpriteP->needsToBeErased = false;
  1784.             
  1785.             curSpriteP = curSpriteP->nextActiveSpriteP;
  1786.         }
  1787.     }
  1788.     
  1789.         // dispose of flagged background rects
  1790.     nextRectStructP = spriteWorldP->headUpdateRectP;
  1791.     while ( nextRectStructP != NULL )
  1792.     {
  1793.         curRectStructP = nextRectStructP;
  1794.         nextRectStructP = curRectStructP->nextRectStructP;
  1795.         DisposePtr( (Ptr)curRectStructP );
  1796.     }
  1797.     spriteWorldP->headUpdateRectP = NULL;
  1798.     
  1799.     spriteWorldP->numTilesChanged = 0;
  1800.     
  1801.         // Remove the deadSpriteLayer if we added it earlier.
  1802.     if ( spriteWorldP->deadSpriteLayerP->headSpriteP != NULL )
  1803.     {
  1804.         SWRemoveSpriteLayer(spriteWorldP, spriteWorldP->deadSpriteLayerP);
  1805.     }
  1806. }
  1807.  
  1808.     
  1809. ///--------------------------------------------------------------------------------------
  1810. //    SWCheckIdleSpriteOverlap
  1811. ///--------------------------------------------------------------------------------------
  1812.  
  1813. SW_FUNC void SWCheckIdleSpriteOverlap(
  1814.     SpriteWorldPtr            spriteWorldP,
  1815.     register SpritePtr        idleSpriteP,
  1816.     SpritePtr                headActiveSpriteP)
  1817. {
  1818.     register SpritePtr         activeSpriteP = headActiveSpriteP;
  1819.     Rect                    srcSectRect, dstSectRect;
  1820.     
  1821.         // iterate through the active sprites
  1822.     while (activeSpriteP != NULL)
  1823.     {
  1824.             // do the sprites overlap?
  1825.         if ((idleSpriteP->oldFrameRect.top < activeSpriteP->deltaFrameRect.bottom) &&
  1826.              (idleSpriteP->oldFrameRect.bottom > activeSpriteP->deltaFrameRect.top) &&
  1827.              (idleSpriteP->oldFrameRect.left < activeSpriteP->deltaFrameRect.right) &&
  1828.              (idleSpriteP->oldFrameRect.right > activeSpriteP->deltaFrameRect.left))
  1829.         {
  1830.                 // calculate the intersection between the idle sprite's destination
  1831.                 // rect, and the active sprite's delta rect
  1832.             dstSectRect.left =
  1833.                     SW_MAX(idleSpriteP->destFrameRect.left, activeSpriteP->deltaFrameRect.left);
  1834.             dstSectRect.top =
  1835.                     SW_MAX(idleSpriteP->destFrameRect.top, activeSpriteP->deltaFrameRect.top);
  1836.             dstSectRect.right =
  1837.                     SW_MIN(idleSpriteP->destFrameRect.right, activeSpriteP->deltaFrameRect.right);
  1838.             dstSectRect.bottom =
  1839.                     SW_MIN(idleSpriteP->destFrameRect.bottom, activeSpriteP->deltaFrameRect.bottom);
  1840.             
  1841.             srcSectRect = idleSpriteP->curFrameP->frameRect;
  1842.             
  1843.             srcSectRect.left += (dstSectRect.left - idleSpriteP->destFrameRect.left);
  1844.             srcSectRect.top += (dstSectRect.top - idleSpriteP->destFrameRect.top);
  1845.             srcSectRect.right -= (idleSpriteP->destFrameRect.right - dstSectRect.right);
  1846.             srcSectRect.bottom -= (idleSpriteP->destFrameRect.bottom - dstSectRect.bottom);
  1847.             
  1848.             
  1849.                 // copy a piece of the sprite image onto the workFrame    
  1850.                 
  1851.             gCurrentSpriteBeingDrawn = idleSpriteP;
  1852.             
  1853.             (*idleSpriteP->frameDrawProc)(
  1854.                     idleSpriteP->curFrameP,
  1855.                     spriteWorldP->workFrameP,
  1856.                     &srcSectRect,
  1857.                     &dstSectRect);
  1858.  
  1859.             
  1860.             gCurrentSpriteBeingDrawn = NULL;
  1861.             
  1862.             if (spriteWorldP->tilingIsOn &&
  1863.                 idleSpriteP->tileDepth <= spriteWorldP->lastActiveTileLayer)
  1864.             {
  1865.                     // Clip dstSectRect to visScrollRect
  1866.                 if (dstSectRect.left < spriteWorldP->visScrollRect.left)
  1867.                     dstSectRect.left = spriteWorldP->visScrollRect.left;
  1868.                 if (dstSectRect.right > spriteWorldP->visScrollRect.right)
  1869.                     dstSectRect.right = spriteWorldP->visScrollRect.right;
  1870.                 if (dstSectRect.top < spriteWorldP->visScrollRect.top)
  1871.                     dstSectRect.top = spriteWorldP->visScrollRect.top;
  1872.                 if (dstSectRect.bottom > spriteWorldP->visScrollRect.bottom)
  1873.                     dstSectRect.bottom = spriteWorldP->visScrollRect.bottom;
  1874.  
  1875.                 SWDrawTilesAboveSprite(spriteWorldP, &dstSectRect, idleSpriteP->tileDepth);
  1876.             }
  1877.         }
  1878.         
  1879.         activeSpriteP = activeSpriteP->nextActiveSpriteP;
  1880.     }
  1881. }
  1882.  
  1883.  
  1884. ///--------------------------------------------------------------------------------------
  1885. //    SWCheckIdleSpritesWithTiles - redraw sprites erased by tiles that changed
  1886. ///--------------------------------------------------------------------------------------
  1887.  
  1888. SW_FUNC void SWCheckIdleSpritesWithTiles(
  1889.     SpriteWorldPtr    spriteWorldP,
  1890.     SpritePtr        headIdleSpriteP)
  1891. {
  1892.     Rect        srcSectRect, dstSectRect;
  1893.     register    SpritePtr idleSpriteP;
  1894.     short        srcHorizOffset;
  1895.     short        srcVertOffset;
  1896.     Rect        *changedRectP;
  1897.     short        index;
  1898.     
  1899.  
  1900.         // Cycle through the changedTiles array of rects
  1901.     changedRectP = spriteWorldP->changedTiles;
  1902.     for (index = 0; index < spriteWorldP->numTilesChanged; index++, changedRectP++)
  1903.     {
  1904.         idleSpriteP = headIdleSpriteP;
  1905.     
  1906.             // iterate through the idle sprites
  1907.         while (idleSpriteP != NULL)
  1908.         {
  1909.                 // does the idle sprite overlap the changedRect?
  1910.             if ((idleSpriteP->oldFrameRect.top < changedRectP->bottom) &&
  1911.                  (idleSpriteP->oldFrameRect.bottom > changedRectP->top) &&
  1912.                  (idleSpriteP->oldFrameRect.left < changedRectP->right) &&
  1913.                  (idleSpriteP->oldFrameRect.right > changedRectP->left))
  1914.             {
  1915.                     // calculate the intersection between the idle
  1916.                     // sprite's rect and the changedRectP
  1917.                 dstSectRect.left = 
  1918.                         SW_MAX(idleSpriteP->oldFrameRect.left, changedRectP->left);
  1919.                 dstSectRect.top = 
  1920.                         SW_MAX(idleSpriteP->oldFrameRect.top, changedRectP->top);
  1921.                 dstSectRect.right = 
  1922.                         SW_MIN(idleSpriteP->oldFrameRect.right, changedRectP->right);
  1923.                 dstSectRect.bottom = 
  1924.                         SW_MIN(idleSpriteP->oldFrameRect.bottom, changedRectP->bottom);
  1925.                     
  1926.                     // Calculate the source rect
  1927.                 srcSectRect = dstSectRect;
  1928.                 
  1929.                 srcHorizOffset = idleSpriteP->curFrameP->frameRect.left;
  1930.                 srcVertOffset = idleSpriteP->curFrameP->frameRect.top;
  1931.                 
  1932.                 srcSectRect.left -= (idleSpriteP->oldFrameRect.left - srcHorizOffset);
  1933.                 srcSectRect.right -= (idleSpriteP->oldFrameRect.left - srcHorizOffset);
  1934.                 srcSectRect.top -= (idleSpriteP->oldFrameRect.top - srcVertOffset);
  1935.                 srcSectRect.bottom -= (idleSpriteP->oldFrameRect.top  - srcVertOffset);
  1936.     
  1937.                     // Copy a piece of the sprite image onto the back drop piece
  1938.                 
  1939.                 gCurrentSpriteBeingDrawn = idleSpriteP;    
  1940.                 
  1941.                 (*idleSpriteP->frameDrawProc)(
  1942.                         idleSpriteP->curFrameP,
  1943.                         spriteWorldP->workFrameP,
  1944.                         &srcSectRect,
  1945.                         &dstSectRect);
  1946.                 
  1947.                 gCurrentSpriteBeingDrawn = NULL;
  1948.                 
  1949.                 if (spriteWorldP->tilingIsOn &&
  1950.                     idleSpriteP->tileDepth <= spriteWorldP->lastActiveTileLayer)
  1951.                 {
  1952.                     dstSectRect.top += spriteWorldP->vertScrollRectOffset;
  1953.                     dstSectRect.bottom += spriteWorldP->vertScrollRectOffset;
  1954.                     dstSectRect.left += spriteWorldP->horizScrollRectOffset;
  1955.                     dstSectRect.right += spriteWorldP->horizScrollRectOffset;
  1956.                     SWDrawTilesAboveSprite(spriteWorldP, &dstSectRect, idleSpriteP->tileDepth);
  1957.                 }
  1958.             }
  1959.             
  1960.             idleSpriteP = idleSpriteP->nextIdleSpriteP;
  1961.         }
  1962.     }
  1963. }
  1964.  
  1965.  
  1966. ///--------------------------------------------------------------------------------------
  1967. //    SWCheckIdleSpritesWithRects - redraw sprites erased by updateRects
  1968. ///--------------------------------------------------------------------------------------
  1969.  
  1970. SW_FUNC void SWCheckIdleSpritesWithRects(
  1971.     SpriteWorldPtr    spriteWorldP,
  1972.     SpritePtr        headIdleSpriteP)
  1973. {
  1974.     UpdateRectStructPtr    curRectStructP;
  1975.     register SpritePtr    idleSpriteP;
  1976.     Rect                srcSectRect, dstSectRect;
  1977.     short                srcHorizOffset;
  1978.     short                srcVertOffset;
  1979.     Rect                *changedRectP;
  1980.     
  1981.     
  1982.     curRectStructP = spriteWorldP->headUpdateRectP;
  1983.     
  1984.     while (curRectStructP != NULL)
  1985.     {
  1986.         changedRectP = &curRectStructP->updateRect;
  1987.         idleSpriteP = headIdleSpriteP;
  1988.     
  1989.             // iterate through the idle sprites
  1990.         while (idleSpriteP != NULL)
  1991.         {
  1992.                 // does the idle sprite overlap the changedRect?
  1993.             if ((idleSpriteP->oldFrameRect.top < changedRectP->bottom) &&
  1994.                  (idleSpriteP->oldFrameRect.bottom > changedRectP->top) &&
  1995.                  (idleSpriteP->oldFrameRect.left < changedRectP->right) &&
  1996.                  (idleSpriteP->oldFrameRect.right > changedRectP->left))
  1997.             {
  1998.                     // calculate the intersection between the idle
  1999.                     // sprite's rect and the changedRectP
  2000.                 dstSectRect.left = 
  2001.                     SW_MAX(idleSpriteP->oldFrameRect.left, changedRectP->left);
  2002.                 dstSectRect.top = 
  2003.                     SW_MAX(idleSpriteP->oldFrameRect.top, changedRectP->top);
  2004.                 dstSectRect.right = 
  2005.                     SW_MIN(idleSpriteP->oldFrameRect.right, changedRectP->right);
  2006.                 dstSectRect.bottom = 
  2007.                     SW_MIN(idleSpriteP->oldFrameRect.bottom, changedRectP->bottom);
  2008.                     
  2009.                     // Calculate the source rect
  2010.                 srcSectRect = dstSectRect;
  2011.                 
  2012.                 srcHorizOffset = idleSpriteP->curFrameP->frameRect.left;
  2013.                 srcVertOffset = idleSpriteP->curFrameP->frameRect.top;
  2014.                 
  2015.                 srcSectRect.left -= (idleSpriteP->oldFrameRect.left - srcHorizOffset);
  2016.                 srcSectRect.right -= (idleSpriteP->oldFrameRect.left - srcHorizOffset);
  2017.                 srcSectRect.top -= (idleSpriteP->oldFrameRect.top - srcVertOffset);
  2018.                 srcSectRect.bottom -= (idleSpriteP->oldFrameRect.top  - srcVertOffset);
  2019.     
  2020.                     // Copy a piece of the sprite image onto the back drop piece    
  2021.                 
  2022.                 gCurrentSpriteBeingDrawn = idleSpriteP;
  2023.  
  2024.                 (*idleSpriteP->frameDrawProc)(
  2025.                         idleSpriteP->curFrameP,
  2026.                         spriteWorldP->workFrameP,
  2027.                         &srcSectRect,
  2028.                         &dstSectRect);
  2029.                 
  2030.                 gCurrentSpriteBeingDrawn = NULL;
  2031.                 
  2032.                 if (spriteWorldP->tilingIsOn &&
  2033.                     idleSpriteP->tileDepth <= spriteWorldP->lastActiveTileLayer)
  2034.                 {
  2035.                     dstSectRect.top += spriteWorldP->vertScrollRectOffset;
  2036.                     dstSectRect.bottom += spriteWorldP->vertScrollRectOffset;
  2037.                     dstSectRect.left += spriteWorldP->horizScrollRectOffset;
  2038.                     dstSectRect.right += spriteWorldP->horizScrollRectOffset;
  2039.                     SWDrawTilesAboveSprite(spriteWorldP, &dstSectRect, idleSpriteP->tileDepth);
  2040.                 }
  2041.             }
  2042.             
  2043.             idleSpriteP = idleSpriteP->nextIdleSpriteP;
  2044.         }
  2045.         
  2046.         curRectStructP = curRectStructP->nextRectStructP;
  2047.     }
  2048. }
  2049.  
  2050.  
  2051. ///--------------------------------------------------------------------------------------
  2052. //    SWFindSpritesToBeRemoved
  2053. ///--------------------------------------------------------------------------------------
  2054.  
  2055. SW_FUNC void SWFindSpritesToBeRemoved(
  2056.     SpriteWorldPtr spriteWorldP )
  2057. {
  2058.     SpritePtr        curSpriteP, nextSpriteP;
  2059.     
  2060.     curSpriteP = spriteWorldP->deadSpriteLayerP->headSpriteP;
  2061.         
  2062.         // iterate through the sprites in the deadSpriteLayerP
  2063.     while (curSpriteP != NULL)
  2064.     {    
  2065.         nextSpriteP = curSpriteP->nextSpriteP;
  2066.         
  2067.             // all the Sprites here should need removing...
  2068.         SW_ASSERT(curSpriteP->spriteRemoval != kSWDontRemoveSprite);
  2069.         
  2070.             // has this sprite been erased by SWAnimate?
  2071.         if (curSpriteP->needsToBeErased == false)
  2072.         {
  2073.                 // if so, we can safely remove it from its layer
  2074.             SWRemoveSprite(curSpriteP);
  2075.             
  2076.                 // do we want to dispose of this sprite too?
  2077.             if (curSpriteP->spriteRemoval == kSWRemoveAndDisposeSprite)
  2078.                 SWDisposeSprite(&curSpriteP);
  2079.             else
  2080.                 curSpriteP->spriteRemoval = kSWDontRemoveSprite;    // We're done
  2081.         }
  2082.         
  2083.         curSpriteP = nextSpriteP;
  2084.     }
  2085. }
  2086.  
  2087.  
  2088. ///--------------------------------------------------------------------------------------
  2089. //    SWFlagRectAsChanged
  2090. ///--------------------------------------------------------------------------------------
  2091.  
  2092. SW_FUNC OSErr SWFlagRectAsChanged(
  2093.     SpriteWorldPtr spriteWorldP,
  2094.     Rect*    theChangedRect)
  2095. {
  2096.     UpdateRectStructPtr        curRectStructP,
  2097.                             newUpdateRectP;
  2098.     short                    temp;
  2099.     OSErr                    err = noErr;
  2100.     
  2101.         // align the left edge to long word boundary
  2102.     theChangedRect->left &= (spriteWorldP->workFrameP->leftAlignFactor);
  2103.     
  2104.         // align the right edge to long word boundary
  2105.     temp = theChangedRect->right & spriteWorldP->workFrameP->rightAlignFactor;
  2106.     if (temp != 0)
  2107.     {
  2108.         theChangedRect->right += (spriteWorldP->workFrameP->rightAlignFactor + 1) - temp;
  2109.     }
  2110.                     
  2111.     newUpdateRectP = (UpdateRectStructPtr)NewPtr(sizeof(UpdateRectStruct));
  2112.     if ( newUpdateRectP != NULL )
  2113.     {
  2114.         newUpdateRectP->updateRect = *theChangedRect;
  2115.         newUpdateRectP->nextRectStructP = NULL;
  2116.         
  2117.         if ( spriteWorldP->headUpdateRectP == NULL )
  2118.         {
  2119.             spriteWorldP->headUpdateRectP = newUpdateRectP;
  2120.         }
  2121.         else
  2122.         {
  2123.             curRectStructP = spriteWorldP->headUpdateRectP;
  2124.             while ( curRectStructP->nextRectStructP != NULL )
  2125.             {
  2126.                 curRectStructP = curRectStructP->nextRectStructP;
  2127.             }
  2128.             curRectStructP->nextRectStructP = newUpdateRectP;
  2129.         }
  2130.     }
  2131.     else
  2132.     {
  2133.         err = MemError();
  2134.     }
  2135.     
  2136.     return err;
  2137. }
  2138.  
  2139.  
  2140. ///--------------------------------------------------------------------------------------
  2141. //    SWFlagScrollingRectAsChanged - same as SWFlagRectAsChanged, minus alignment code
  2142. ///--------------------------------------------------------------------------------------
  2143.  
  2144. SW_FUNC OSErr SWFlagScrollingRectAsChanged(
  2145.     SpriteWorldPtr spriteWorldP,
  2146.     Rect*    theChangedRect)
  2147. {
  2148.     UpdateRectStructPtr        curRectStructP,
  2149.                             newUpdateRectP;
  2150.     OSErr                    err = noErr;
  2151.     
  2152.                     
  2153.     newUpdateRectP = (UpdateRectStructPtr)NewPtr(sizeof(UpdateRectStruct));
  2154.     if ( newUpdateRectP != NULL )
  2155.     {
  2156.         newUpdateRectP->updateRect = *theChangedRect;
  2157.         newUpdateRectP->nextRectStructP = NULL;
  2158.         
  2159.         if ( spriteWorldP->headUpdateRectP == NULL )
  2160.         {
  2161.             spriteWorldP->headUpdateRectP = newUpdateRectP;
  2162.         }
  2163.         else
  2164.         {
  2165.             curRectStructP = spriteWorldP->headUpdateRectP;
  2166.             while ( curRectStructP->nextRectStructP != NULL )
  2167.             {
  2168.                 curRectStructP = curRectStructP->nextRectStructP;
  2169.             }
  2170.             curRectStructP->nextRectStructP = newUpdateRectP;
  2171.         }
  2172.     }
  2173.     else
  2174.     {
  2175.         err = MemError();
  2176.     }
  2177.     
  2178.     return err;
  2179. }
  2180.  
  2181.  
  2182. ///--------------------------------------------------------------------------------------
  2183. //    SWSetSpriteWorldMaxFPS
  2184. ///--------------------------------------------------------------------------------------
  2185.  
  2186. SW_FUNC void SWSetSpriteWorldMaxFPS(
  2187.     SpriteWorldPtr spriteWorldP,
  2188.     short framesPerSec)
  2189. {
  2190.     SW_ASSERT(spriteWorldP != NULL);
  2191.     
  2192.         // is framesPerSec a valid value?
  2193.     if (framesPerSec > 0 && framesPerSec <= 1000 )
  2194.     {
  2195.         spriteWorldP->fpsTimeInterval = 1000/framesPerSec;
  2196.     }
  2197.         // framesPerSec is an "ignore it" value.
  2198.     else
  2199.     {
  2200.         spriteWorldP->fpsTimeInterval = 0;
  2201.     }
  2202. }
  2203.  
  2204.  
  2205. ///--------------------------------------------------------------------------------------
  2206. // SWSyncSpriteWorldToVBL
  2207. ///--------------------------------------------------------------------------------------
  2208.  
  2209. SW_FUNC OSErr SWSyncSpriteWorldToVBL(
  2210.     SpriteWorldPtr    spriteWorldP,
  2211.     Boolean            syncingOn)
  2212. {
  2213.     OSErr            err = noErr;
  2214.     AuxDCEHandle    mainDCE;
  2215.     
  2216.     SW_ASSERT(spriteWorldP != NULL);        
  2217.     
  2218.     if ( syncingOn )
  2219.     {
  2220.         if ( !spriteWorldP->usingVBL )
  2221.         {    
  2222.             *((VBLUPP*)&spriteWorldP->vblTaskRec.myVBLTask.vblAddr) =
  2223.                 NewVBLProc((ProcPtr)SWVBLTask);
  2224.             spriteWorldP->vblTaskRec.myVBLTask.qType = vType;
  2225.             spriteWorldP->vblTaskRec.myVBLTask.vblCount = 1;
  2226.             spriteWorldP->vblTaskRec.hasVBLFired = false;
  2227.             
  2228.                 // insert the task into the VBL queue
  2229.             mainDCE = (AuxDCEHandle)GetDCtlEntry((**spriteWorldP->mainSWGDH).gdRefNum);
  2230.             err = SlotVInstall( (QElemPtr) &spriteWorldP->vblTaskRec.myVBLTask, 
  2231.                     (**mainDCE).dCtlSlot );
  2232.             if ( err == noErr )
  2233.             {
  2234.                 spriteWorldP->usingVBL = true;
  2235.             }
  2236.         }
  2237.     }
  2238.     else
  2239.     {
  2240.         if ( spriteWorldP->usingVBL )
  2241.         {
  2242.             mainDCE = (AuxDCEHandle)GetDCtlEntry((**spriteWorldP->mainSWGDH).gdRefNum);
  2243.             err = SlotVRemove( (QElemPtr) &spriteWorldP->vblTaskRec.myVBLTask, 
  2244.                     (**mainDCE).dCtlSlot );
  2245.             spriteWorldP->vblTaskRec.hasVBLFired = true;
  2246.             spriteWorldP->usingVBL = false;
  2247.             DisposeRoutineDescriptor(spriteWorldP->vblTaskRec.myVBLTask.vblAddr);
  2248.         }
  2249.     }
  2250.  
  2251.     SWSetStickyIfError( err );
  2252.     return err;
  2253. }
  2254.  
  2255.  
  2256. ///--------------------------------------------------------------------------------------
  2257. // SWVBLTask
  2258. ///--------------------------------------------------------------------------------------
  2259.  
  2260. #if !GENERATINGCFM
  2261. extern    VBLTaskRecPtr GetVBLRec(void)
  2262.     = 0x2008;    /* MOVE.L    A0,D0 */
  2263. #endif
  2264.  
  2265. #if GENERATINGCFM
  2266. void SWVBLTask(VBLTaskRecPtr vblTaskPtr)
  2267. {
  2268.     vblTaskPtr->hasVBLFired = true;
  2269.     
  2270.         // Reset vblCount so that this procedure executes again
  2271.     vblTaskPtr->myVBLTask.vblCount = 1;
  2272. }
  2273. #else
  2274. void SWVBLTask( void )
  2275. {
  2276.     VBLTaskRecPtr vblTaskPtr;
  2277.     
  2278.     vblTaskPtr = (VBLTaskRecPtr) GetVBLRec();
  2279.     vblTaskPtr->hasVBLFired = true;
  2280.     
  2281.         // Reset vblCount so that this procedure executes again
  2282.     vblTaskPtr->myVBLTask.vblCount = 1;
  2283. }
  2284. #endif
  2285.  
  2286.  
  2287. ///--------------------------------------------------------------------------------------
  2288. //    SWSetCleanUpSpriteWorld - call this if you want FatalError() or SWAssertFail() to call 
  2289. //    SWSyncSpriteWorldToVBL with a value of false for your SpriteWorld before it calls
  2290. //    ExitToShell. You pass a pointer to the SpriteWorld you want to be "cleaned up".
  2291. ///--------------------------------------------------------------------------------------
  2292.  
  2293. void    SWSetCleanUpSpriteWorld(SpriteWorldPtr spriteWorldP)
  2294. {
  2295.     gCleanUpSpriteWorldP = spriteWorldP;
  2296. }
  2297.  
  2298.  
  2299. ///--------------------------------------------------------------------------------------
  2300. //    SWGetSpriteWorldVersion
  2301. ///--------------------------------------------------------------------------------------
  2302.  
  2303. SW_FUNC unsigned long SWGetSpriteWorldVersion(void)
  2304. {
  2305.     return 0x02210000;
  2306. }
  2307.